4

请注意,这个问题与 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(不修改任何内容)?

4

1 回答 1

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 通过将此闭包列表传递给此构建器来完成此操作,该构建器将覆盖 invokeMethod 来完成工作,如此处所述

于 2012-12-25T21:19:44.547 回答