Play framework 2.0 betaが出たようです4 – ControllerとRouting
コントローラーとHTTPルーティング
今回もGithubにあるwikiをベースにPlay framework2.0を動かしていきます。 ここにあるドキュメントはドラフトですが、ひととおりの機能を解説しています。 このドキュメントはJava版とScala版があり、それぞれの言語での使い方を説明しています。 いままでもそうでしたが、この記事ではScala版を見ながら解説していきます。 今回使用した動作環境は以下のとおりです。
- OS : MacOS X 10.7.2
- Playframework : 2.0β
- Java : 1.6.0_26
注意: この記事ではβ版を使用しています。 正式リリース前の状況のため思わぬ不具合が生じるかもしれませんので、ご了承ください。
ActionとController
Controllerについては、wikiのControllers and Actions ※1で説明しています。 ここの説明にそって解説を進めていきます。
まずはControllerについての説明です。 PlayframeworkにおいてControllerは、HTTPリクエストを受けてそれらを解析し、下位のモデルレイヤーに処理を渡します。 したがってこのレイヤーでは、リクエストやレスポンス(playのクラスにラップされてますが)を使用することが多いです。
基本的なController
プロジェクト作成時に雛形として提供されるControllerです。
package controllers import play.api._ import play.api.mvc._ object Application extends Controller { def index = Action { Ok("It works!") } }
playのControllerはシングルトンオブジェクトで、 play.api.mvc.Controller のサブクラスとして定義されます。 Scalaなので同一のファイル内に任意の数のControllerを記述できます。
Actionとは
Controllerの関数の戻り値であるAction は、Requestを引数にとり、Result(を実装したクラス)を返します。 下記のサンプルは、Ok(Results.Ok)を返しています。これはHTTPステータスの200をtext/plain形式で返します。
val echo = Action { request => Ok("Got request [" + request + "]") }
基本的なAction
ここでいくつかActionのパターンを確認してみます。 ControllerではHTTPリクエストが必要になることが多いですが、play.api.mvc.RequestをAction内で使用可能です。
def index = Action { request => val name = request.queryString.get("name").flatMap(_.headOption) Ok("Hello " + name.getOrElse("Guest")) }
Controllerに定義する関数はパラメータを持つことができますし、それをAction内で使用することも可能です。
def hello(name: String) = Action { Ok("Hello " + name) }
Actionの構成
アクションの構成は簡単で、下記のようにすれば認証とキャッシュを適用したActionを使用できます。
def hello(name: String) = { Authenticated { Cached { Action { Ok("Hello " + name) } } } }
HTTPルーティング
HTTPルーティングについては、wikiのHttp Routing ※2で説明しています。 ここの説明にそって解説を進めていきます。
HTTPルーターは、conf/routesに定義してあるパスをチェックし、 リクエストされたURLに応じてControllerに定義してある関数を呼び出しを行います。 このconf/routesファイル内容はコンパイルされ、エラーの際には直接ブラウザでroutesのエラーが表示されます。
routesの書き方
confroutesファイルはルーターによって使用される構成ファイルです。 このファイルは、playアプリケーションに必要なすべてのルートを記述しています。 各ルートはHTTPメソッド、URIパターン、Actionを返すControllerの関数に紐付けられています。
GET / controllers.Application.index #これはコメント POST /user/:id controllers.UserController.show(id:Long)
HTTP methodのパターン
HTTP methodについては、GET、POST、PUT、 DELETE、 HEADを記述することができます。
URIのパターン
URIパターンは、HTTPルートのリクエストパスを定義します。リクエストパスの部分は動的に定義することも可能です。
#これは静的なパス GET /clients/all controllers.Clients.list() #これは動的なパス GET /clients/:id controllers.Clients.show(id: Long)
例えば、IDによってクライアントを取得するルートを定義する場合、:idのようにして動的な部分を追加します。 デフォルトのURIマッチングパターンは正規表現で"[^/]+"となっています。 さらに、ワイルドカードを使用することもできますし、 $id<regex>のようにして正規表現を使用することもできます。
#/files/image/logo.png などがマッチする GET /files/*name controllers.Application.download(name) #/clients/12345 などがマッチする GET /clients/$id<[0-9]+> controllers.Clients.show(id: Long)
ControllerのActionジェネレータ関数を呼ぶ場合
ルート定義の最後の部分はControllerの関数呼び出し部分です。 この関数は、play.api.mvc.Actionを返す関数でなくてはいけません。 Controllerの関数がパラメータなしの場合、完全修飾メソッド名を記述します。
GET /clients controllers.Clients.index()
controllerの関数はパラメータを取ることも可能です。 URIに埋め込む形式、クエリストリングを使用する形式が使用できます。
#localhost:9000/myidなどとアクセス GET /:id controllers.Application.show(id) #localhost:9000/list?name=helloなどとアクセス GET /list controllers.Application.list(name)
def show(id:String) = Action { Ok(views.html.index("id=" + id)) } def list(name:String) = Action { Ok(views.html.index("name=" + name)) }
パラメータは型を指定することも可能です。
GET /:id controllers.Application.show(id:Long)
def show(id:Long) = Action { Ok(views.html.index("id=" + id)) }
さらに、URIに応じてパラメータを固定にすることも可能ですし、デフォルト値を設定することもできます。
#このURLの場合はid=1で固定 GET / controllers.Application.show(id:Long = 1) #デフォルト値を設定。localhost:9000/listでアクセスすると、nameは"hello"になる GET /list controllers.Application.list(name:String ?="hello")
リバースルーティング
Controllerに定義してある関数は、他のActionジェネレータ関数からも呼び出すことができます。 例えば下記のようなControllerとroutesがあるとします。
package controllers import play.api._ import play.api.mvc._ object Application extends Controller { def hello(name: String) = Action { Ok("Hello " + name + "!") } }
# Hello action GET /hello/:name controllers.Application.hello(name)
他の関数(他のControllerでも可能)から呼び出すことにより、hello関数へURLを送ることができます。 リバースプロキシのような使いかたもできますので、複雑なルーティングの定義もよりシンプルに保つことができます。
// Redirect to /hello/Bob def helloBob = Action { Redirect(controllers.routes.Application.hello("Bob")) }
まとめ
以上、Controller、Action、ルーティングの基本についてご紹介しました。 Play framewokr1.2(play-scala 0.9.1)から大きく変わった点は、Actionの概念ですね。 routesファイルの記述方法などは以前と変更はないようです。(おそらく。。。) 次回は新たに導入された機能、Application global settingsについての解説を予定しています。