请注意,这个问题并不直接与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")
执行UrlMappings的名为/ foo的函数.如果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应该在映射闭包内执行时,groovy将在我的委托映射中查找名为/ foo的键.因此使用MyMap的get()方法.如果不存在具有此名称的密钥,则将创建一个新密钥.键的值始终是一个将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
我希望这段代码应该打印名为:[arg:foo]的字符串.但是我得到:
groovy.lang.MissingMethodException: No signature of method: Test.foo() is applicable for argument types: (java.util.LinkedHashMap) values: [[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(它不会修改任何东西)?
最佳答案 你读过关于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