Sharable

システム&ウェブのシェアラブル

Lv.2 Playフレームワークのルート処理って大切。 [play framework2.0][java]

2012年3月22日

レベル2は、conf/routesファイルの説明です。
これはどのURLを叩くと、どのクラスのどのメソッドが呼ばれるか、を定義する
ファイルです。
strutsとかspringとかseasar2とか他のフレームワークでもお馴染みの機構です。

ただこれらと違い、記述方法がXMLじゃないので、多少慣れが必要になります。

でも簡単です。

1:静的なURLの設定

記述方法を記します。

GET   /clients    controllers.Clients.list()

こういう形になっていて、構造的には、

動詞 URL Actionメソッドのフルパス
GET /clients controllers.Clients.list()

と、これが基本です。

動詞部分には、GET, POST, PUT, DELETE, HEADが適用できるようです。

これを和訳(?)すると、
GET/clientsが叩かれたらcontrollers.Clientsクラスのlist()を実行します」
という感じ。

慣れたら簡単ですよね。

2:動的なURLの設定

上述は静的なURLの定義でして、動的な定義もできます。

┗2-1:URLを動的にする基本

こんな感じです。

GET    /clients/:id    controllers.Clients.show(id)  

/:idが加わりました。
動的なURLはすべて「/」から始まります。
正規表現だと[^/]+という状態です。

これを和訳すると
「GETで/clients/123が呼ばれたらcontrollers.Clientsクラスのshow(id)を実行します」

これでOKです。

┗2-2:URLの詳しい定義

OKですが、このままだと/clients/abcと叩かれた場合でもcontrollers.Clients.show(id)
が実行されます。
それが仕様なら問題ありません。

しかし、/clients/123と/clients/abcでは振る舞いが異なる仕様の場合は、以下の
ように正規表現を利用して定義します。

GET    /clients/$id<&#91;0-9&#93;+>    controllers.Clients.show(id)

これで、idが数字の場合のみcontrollers.Clients.show(id)が呼ばれます。

ホッ…

┗2-3:引数の詳しい定義

っとしたのもタバノマ(=ツカノマ=束の間)です。

もしあなたのプロジェクトで、controllers.Clients.クラスに
show(String id)とshow(Long id)という2つのアクションが記述してある場合、
このままだと予期せぬ動作をしてしまいます。

っというのも、play!ではcontrollers.Clients.show(id)という記述は、
デフォルトでString idと解釈されるからです。

/clients/$id<[0-9]+>と定義しているからといって、数字つながりでLong idの方を
実行してはくれません。

でも大丈夫です。
「引数:型」と指定してあげれば、ちゃんとshow(Long id)を実行してくれます。

ちなみにジェネリクスの場合は、List[String]と記述する模様。
GET    /clients/$id<&#91;0-9&#93;+>   controllers.Clients.show(id:Long)

このように、

  • URL側を正規表現で定義する
  • アクションの引数は型も定義する

というのが一番カッチリした記述方法になります。

┗2-4:重複したメソッドの定義

上述のURL正規表現+アクション引数の型指定を使って、conf/routes上でオーバーライドの
ような振る舞いをすることができるでしょうか。

GET  /clients/$id<&#91;0-9&#93;+>  controllers.Clients.show(id:Long)
GET  /clients/$id<&#91;a-z&#93;+>  controllers.Clients.show(id:String)

残念ながら(?)これはコンパイルエラーが発生します。

3:その他の記述方法

上述が基本形として、他にも下記のような定義があります。

┗3-1:クエリを引数にする

// http://example.com/?page=index
GET    /    controllers.Application.show(page)

この場合はURLの定義に工夫はなく、単に

  • conf/routesで定義したアクションの引数名:show(page)
  • Javaクラスの引数名:show(String page)
  • クエリのkey:/?page=123

の3者が同名であれば良い。

┗3-2:デフォルト引数も定義できる。「?= 1」

GET    /clients    controllers.Clients.list(page: Integer ?= 1)

ページングなどの処理などに使うとか。

┗3-3:複数のクエリを定義したい。「/.*」

//http://example.com//files/images/logo.png
GET   /files/*name    controllers.Application.download(name)  

もし分かっているなら/files/imagesまでは静的に定義しておいた方がいいかも。
imagesだけじゃなくて、pdfとかもくるかもしれないなら、このくらい曖昧でも
OKかと。

4:競合する定義があった場合

ちなみに、もし競合する定義がファイル内にあったら、一番上のものが優先される。

GET     /:test    controllers.Application.test(test)
GET     /hello    controllers.Application.sayHello()

この状態で、http://localhost:9000/helloとアクセスすると、
controllers.Application.test(test)が実行されます。
定義が増えてきたら分かりづらいですね、、、。
いっそエラー出してほしい気もします。

このエントリーをはてなブックマークに追加