请注意,这个问题与 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
。如果不存在具有此名称的键,则将创建一个新键。键的值始终是一个以映射为参数的闭包。
执行脚本时,我得到:
/foo called: [controller:foo, action:myaction]
/bar called: [controller:bar, action:myaction]
404 called: [controller:error]
!%&/() called: [controller:foo]
所以它奏效了。但是我不知道这是否是 grails 使用的方式。也许有一个更简单的解决方案?
所以我的第一个问题是:还有另一种(可能更简单)的方法吗?/ Grails 如何解决这些函数调用?
当我作为代表尝试使用 Maps 时,出现了另一个问题。
让我们看看这个:
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
(不修改任何内容)?