この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
コントローラーと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についての解説を予定しています。