連載
» 2013年02月21日 18時00分 公開

Scala+Play 2.0でWebアプリ開発入門(4):Playコントローラ/Action/HTTP Routerの基本的な使い方 (2/3)

[中村修太,クラスメソッド]

ControllerオブジェクトやActionの詳細

 次に、ControllerオブジェクトやActionの詳細を説明していきましょう。これらについては、Play framework公式サイトにあるControllerやActionについての解説をベースに進めていきます。

Actionとは

 Controller内での処理は、実際はほとんどplay.api.mvc.Action(以下、Action)が行っています。Actionとは、リクエストを処理してクライアントへ送るレスポンスを生成するためのクラスで、いくつかの形式があります。

 例えば、下記のActionでは「play.api.mvc.Requestを受け取ってplay.api.mvc.Resultを返す関数」を受け取ります。

val echo = Action { request =>
    Ok("Got request [" + request + "]")
}

 Result型が実際にクライアントへ送信されるHTTPレスポンスです。この例で「Ok」という関数は、content typeがtext/plainで、ステータスコード200のレスポンスを生成します。

いくつかのAction定義

 先ほどの例のActionでは、Requestを受け取ってResultを返す関数を受け取るものでした。これ以外にもいくつかActionの形式があります。一番シンプルなActionの形式は、Result型を返す関数を取る形式です。

Action {
    Ok("Hello world")
}

 上記Actionは先ほどの例と同様、ステータスコードが200、Content Typeはtext/plainになり、Body部分は「Hello world」というHTTPレスポンスが返されます。

 次は受け取ったHTTPリクエストにアクセスするためのActionです。HTTPリクエストにアクセスするため、以前のサンプルでも見た「play.api.mvc.Requestを受け取ってplay.api.mvc.Resultを返す関数」を受け取るActionが用意されています。

Action { request =>
    Ok("path:" + request.path)
}

 また、公式ドキュメントのControllerやActionについての解説では、requestパラメータにimplicitを指定し、暗黙的な引数とする方法を紹介しています。

 例えば下記のように、implicitなRequestHeaderを受け取るgreeting関数がある場合、say関数が受け取るrequestをimplicitで宣言しておけば、暗黙でrequestが渡されます(play.api.mvc.RequestはRequestHeaderを継承しています)。

def say = Action { implicit request =>	
    Ok(greeting("Hello"))
}
private def greeting(say: String)(implicit req: RequestHeader) = say + "," + req.remoteAddress

 以上が基本的なActionの使い方です。

Controllerオブジェクトについて

 次はControllerについて説明しましょう。ControllerはActionを生成するobjectで、play.api.mvc.Controllerトレイトをmix-inして実装します。

 先ほど作成したSampleControllerもそうしていますね。conf/routesで定義されたURIにリクエストがきた場合、それとマッピングされたControllerのメソッドが実行されます。

 SampleControllerで定義された関数はパラメータを受け取りませんが、任意のパラメータを受け取る関数を定義してクエリ文字列やPOSTされたパラメータをバインドすることもできます(これについては後述します)。

SimpleResultを使ってレスポンスを返す

 SimpleResultはHTTPレスポンスを表すオブジェクトで、ステータスコードとヘッダ、Bodyを自分で自由に設定できます。SimpleResultはplay.api.mvcパッケージのcaseクラスとして定義されています。

 いままでの例では「Ok」という関数を使用してきました。これは実際はSimpleResultを継承したStatusクラス内で、ステータスコードの「200 OK」を返すヘルパ関数として定義されています。

 先ほど定義したsample1メソッドでOk関数を使用せず、SimpleResultを使って実装すると下記のようになります。

def sample1 = Action {	
    SimpleResult(
        header = ResponseHeader(200, Map(CONTENT_TYPE -> "text/html")), 
        body = Enumerator(views.html.index("Sample Controller#sample1"))
    )
} 

 SimpleResultのコンストラクタにheaderとbodyを渡してHTTPレスポンスを生成しているのが分かります。

よく使用するヘルパ関数

 Statusクラスにはステータスコードに応じたヘルパ関数が多数用意されています。大体がステータスコードそのままの関数名となっており、Body部分のパラメータを受け取れるようになっています。

ステータスコード 関数名
200 OK Ok()
404 NofFound NotFound()
409 Conflict Conflict()
500 Internal Server Error InternalServerError()
※各関数が受け取るbodyはあってもなくても構わない

 上記以外の関数についてはSimpleResultのソースを確認するか、ResultsクラスのScaladocをご確認ください。

 別のURIへリダイレクトさせたいときは、Redirect関数を使用します。フルパスであれば外部のサイトへリダイレクトさせることもできます。

def redirect1 = Action {
    /* http://localhost:9000/sample2へリダイレクト */
    Redirect("/sample2")
}
def redirect2 = Action {
    /* http://www.atmarkit.co.jp/へリダイレクト */	
    Redirect("http://www.atmarkit.co.jp/")
} 

補足 TODOメソッドについて

 Controllerトレイトには「TODO」というメソッドが定義してあります。これは空のAction実装を提供し、まだControllerの実装内容が決まっていない場合などに使います。


object SomethingController extends Controller {
    /* このメソッドはステータスコード501を返します */
    def something = TODO
}

 このコントローラにマッピングされたURIにアクセスした場合、ステータスコード「501 Not Implemented」とともに、未実装の旨を表すページが表示されます。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。