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")

/fooofという名前の関数を実行しますUrlMappingsUrlMappings呼び出された関数が含まれていない場合は/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 はデリゲート マップでmappings指定されたキーを探します。/fooしたがって、 のget()方法MyMapが使用されます。この名前のキーが存在しない場合は、新しいキーが作成されます。キーの値は常に、マップをパラメーターとして受け取るクロージャーです。

スクリプトを実行すると、次のようになります。

/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]"

できます。

だから私の2番目の質問は、なぜこれは単純なものでは機能しない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 に答える