请注意,此问题并非直接与Grails中的url映射有关。它是关于如何定义url映射的方式。
在查看UrlMappings.groovy
时,我们会看到类似的内容:
class UrlMappings {
static mappings = {
"/foo" (controller: "foo", action: "myaction")
"/bar" (controller: "bar", action: "myaction")
"404" (controller: 'error')
}
}
括号表示有一个函数/方法调用。从我的理解行
"/foo" (controller: "foo", action: "myaction")
执行/foo
的名为UrlMappings
的函数。如果UrlMappings
不包含名为/foo
的函数,则会查看闭包委托。
我的问题是你可以在mappings = { .. }
内使用的字符串不受限制。您可以添加任何您想要的定义。例如:
"!%&/()" (controller: "foo")
因此必须采用某种动态方式来定义这些功能。我想不出在UrlMappings
类中定义这些函数的解决方案。所以我尝试使用闭包委托来提出解决方案。
使用简单的groovy脚本,我尝试了以下哪种方式对我很好:
def mappings = {
"/foo" (controller: "foo", action: "myaction")
"/bar" (controller: "bar", action: "myaction")
"404" (controller: 'error')
"!%&/()" (controller: "foo")
}
class MyMap extends LinkedHashMap {
@Override
public Object get(Object key) {
if (!this.containsKey(key)) {
this.put(key, { Map map -> println "$key called: $map" })
}
return super.get(key);
}
}
mappings.delegate = new MyMap()
mappings()
因此,当/foo
在mappings
闭包内执行时,groovy会在我的委托贴图中查找名为/foo
的键。因此,使用get()
MyMap
方法。如果不存在具有此名称的密钥,则将创建一个新密钥。键的值始终是一个闭包,它将map作为参数。
执行脚本时我得到:
/foo called: [controller:foo, action:myaction]
/bar called: [controller:bar, action:myaction]
404 called: [controller:error]
!%&/() called: [controller:foo]
所以它奏效了。但是我不知道这是否是grails使用的方式。也许有一个更简单的解决方案?
所以我的第一个问题是:还有另一种(可能更容易)的方法吗? / Grails如何解决这些函数调用?
当我作为代表尝试使用地图时,出现了另一个问题。
让我们来看看:
def closure = {
"foo" (arg: "foo")
}
closure.delegate = ["foo": { Map map -> println "called: $map" }]
closure() // error
我希望这段代码可以打印字符串called: [arg:foo]
。但是我明白了:
groovy.lang.MissingMethodException:没有方法签名:Test.foo()适用于参数类型:(java.util.LinkedHashMap)值:[[arg:foo]]
然后我尝试了以下结果(如预期的那样)在相同的例外中:
def delegate = new LinkedHashMap()
delegate["foo"] = { Map map -> println "called: $map" }
closure.delegate = delegate
closure() // error
但是,如果我这样做:
class MyLinkedHashMap extends LinkedHashMap { }
def delegate = new MyLinkedHashMap()
delegate["foo"] = { Map map -> println "called: $map" }
closure.delegate = delegate
closure() // prints "called: [arg:foo]"
有效。
所以我的第二个问题是:为什么这不适用于简单的LinkedHashMap
,但适用于MyLinkedHashMap
(不会修改任何内容)?
答案 0 :(得分:2)
你读过关于methodMissing的内容吗?
示例如下:http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
另一个:http://blog.vladimirvivien.com/2008/02/25/creating-a-simple-builder-with-groovys-methodmissing/
grails通过将此闭包列表传递给this builder来覆盖invokeMethod来完成工作,as explained here