§HTTPルーティング
§組み込みHTTPルーター
ルーターは、各着信HTTPリクエストをアクション呼び出し(コントローラークラスのパブリックメソッド)に変換するコンポーネントです。
HTTPリクエストは、MVCフレームワークによってイベントとして認識されます。このイベントには、2つの主要な情報が含まれています。
- リクエストパス(
/clients/1542
、/photos/list
など)とクエリ文字列。 - HTTPメソッド(GET、POSTなど)。
ルートは、コンパイルされるconf/routes
ファイルで定義されます。つまり、ルートエラーはブラウザで直接確認できます。
§依存性注入
Playのデフォルトのルートジェネレーターは、@Inject
アノテーション付きのコンストラクターでコントローラーインスタンスを受け入れるルータークラスを作成します。つまり、このクラスは依存性注入での使用に適しており、コンストラクターを使用して手動でインスタンス化することもできます。
Play 2.7.0より前は、Playはアクションをstatic
メソッドとして定義することをサポートする静的ルートジェネレーターをサポートしていました。Playは静的状態に依存しなくなったため、これはサポートされなくなりました。独自の静的状態を使用したい場合は、インスタンスメソッドを使用してコントローラーで引き続き使用できます。
§ルートファイルの構文
conf/routes
は、ルーターが使用する構成ファイルです。このファイルには、アプリケーションに必要なすべてのルートがリストされています。各ルートは、HTTPメソッドとURIパターンで構成され、アクションメソッドの呼び出しに関連付けられています。
ルート定義がどのようなものかを見てみましょう
GET /clients/:id controllers.Clients.show(id: Long)
注:アクション呼び出しでは、パラメータ型はScalaのようにパラメータ名の後に来ます。
各ルートはHTTPメソッドで始まり、その後にURIパターンが続きます。ルートの最後の要素は呼び出し定義です。
#
文字を使用して、ルートファイルにコメントを追加することもできます。
# Display a client.
GET /clients/:id controllers.Clients.show(id: Long)
+
で始まる行でルートを先行することにより、修飾子を適用することもできます。これにより、特定のPlayコンポーネントの動作を変更できます。そのような修飾子の1つは、CSRFフィルターをバイパスする「nocsrf」修飾子です。
+ nocsrf
POST /api/new controllers.Api.newThing()
§HTTPメソッド
HTTPメソッドには、HTTP(GET
、PATCH
、POST
、PUT
、DELETE
、HEAD
、OPTIONS
)でサポートされている有効なメソッドのいずれかを使用できます。
§URIパターン
URIパターンは、ルートのリクエストパスを定義します。リクエストパスの一部は動的にできます。
§静的パス
たとえば、GET /clients/all
の着信リクエストを正確に一致させるには、このルートを定義できます
GET /clients/all controllers.Clients.list()
§動的部分
たとえば、IDでクライアントを取得するルートを定義する場合は、動的部分を追加する必要があります
GET /clients/:id controllers.Clients.show(id: Long)
注:URIパターンには、複数の動的部分を含めることができます。
動的部分のデフォルトのマッチング戦略は、正規表現[^/]+
によって定義されます。これは、:id
として定義された動的部分が1つのURIパスセグメントと正確に一致することを意味します。他のパターンタイプとは異なり、パスセグメントは、コントローラーに渡される前にルートで自動的にURIデコードされ、逆ルートでエンコードされます。
§複数の/にまたがる動的部分
動的部分で、フォワードスラッシュで区切られた複数のURIパスセグメントをキャプチャする場合は、*id
構文(.*
正規表現を使用するワイルドカードパターンとも呼ばれる)を使用して動的部分を定義できます。
GET /files/*name controllers.Application.download(name)
ここで、GET /files/images/logo.png
のようなリクエストの場合、name
の動的部分はimages/logo.png
の値をキャプチャします。
複数の/
にまたがる動的部分は、ルーターによってデコードされず、逆ルーターによってエンコードされないことに注意してください。ユーザー入力と同じように、未加工のURIセグメントを検証するのはあなたの責任です。逆ルーターは単に文字列連結を実行するため、結果のパスが有効であり、たとえば、複数の先頭のスラッシュまたは非ASCII文字が含まれていないことを確認する必要があります。
§カスタム正規表現を使用した動的部分
$id<regex>
構文を使用して、動的部分に独自の正規表現を定義することもできます。
GET /items/$id<[0-9]+> controllers.Items.show(id: Long)
ワイルドカードルートと同様に、パラメータはルーターによってデコードされず、逆ルーターによってエンコードされません。そのコンテキストで意味があることを確認するために、入力を検証するのはあなたの責任です。
§アクションジェネレーターメソッドの呼び出し
ルート定義の最後の部分は、呼び出しです。この部分では、アクションメソッドへの有効な呼び出しを定義する必要があります。
メソッドがパラメータを定義しない場合は、完全修飾メソッド名のみを指定します
GET / controllers.Application.homePage()
アクションメソッドがパラメータを定義する場合、対応するパラメータ値は、URIパス自体から抽出されるか、クエリ文字列から抽出されるかのいずれかで、リクエストURIで検索されます。
# Extract the page parameter from the path.
# i.e. http://myserver.com/index
GET /:page controllers.Application.show(page)
または
# Extract the page parameter from the query string.
# i.e. http://myserver.com/?page=index
GET / controllers.Application.show(page)
これが、controllers.Application
コントローラーの対応するshow
メソッドの定義です。
public Result show(String page) {
String content = Page.getContentOf(page);
return ok(content).as("text/html");
}
§パラメータ型
String
型のパラメータの場合、パラメータ型はオプションです。Playに着信パラメータを特定のScala型に変換させたい場合は、明示的な型を追加できます。
GET /clients/:id controllers.Clients.show(id: Long)
次に、コントローラーの対応するアクションメソッドパラメータに同じ型を使用します
public Result show(Long id) {
Client client = clientService.findById(id);
return ok(views.html.Client.show(client));
}
注:パラメータ型は、サフィックス構文を使用して指定されます。また、Javaの場合と同様に、ジェネリック型は
<>
ではなく[]
記号を使用して指定されます。たとえば、List[String]
はJavaのList<String>
と同じ型です。
§固定値を持つパラメータ
パラメータに固定値を使用したい場合があります。
# Extract the page parameter from the path, or fix the value for /
GET / controllers.Application.show(page = "home")
GET /:page controllers.Application.show(page)
§デフォルト値を持つパラメータ
着信リクエストで値が見つからない場合に使用されるデフォルト値を指定することもできます。
# Pagination links, like /clients?page=3
GET /clients controllers.Clients.list(page: Int ?= 1)
§オプションのパラメータ
すべてのリクエストに存在する必要がないオプションのパラメータを指定することもできます。
# The version parameter is optional. E.g. /api/list-all?version=3.0
GET /api/list-all controllers.Api.list(version ?= null)
# or
GET /api/list-all controllers.Api.listOpt(version: java.util.Optional[String])
§リストパラメータ
繰り返しクエリ文字列パラメータのリストパラメータを指定することもできます。
# The item parameter is a list.
# E.g. /api/list-items?item=red&item=new&item=slippers
GET /api/list-items controllers.Api.listItems(item: java.util.List[String])
# or
# E.g. /api/list-int-items?item=1&item=42
GET /api/list-int-items controllers.Api.listIntItems(item: java.util.List[Integer])
§現在リクエストをアクションメソッドに渡す
現在リクエストをアクションメソッドに渡すこともできます。パラメータとして追加するだけです
GET / controllers.Application.dashboard(request: Request)
および対応するアクションメソッド
public Result dashboard(Http.Request request) {
return ok("Hello, your request path " + request.path());
}
Playは、型Request
(これはplay.mvc.Http.Request
のインポート)のルートパラメータを自動的に検出し、実際のリクエストを対応するアクションメソッドのパラメータに渡します。もちろん、Request
パラメータを他のパラメータと混在させることができ、Request
パラメータがどの位置にあるかは関係ありません。
§ルーティングの優先度
多くのルートが同じリクエストに一致する可能性があります。競合がある場合、最初(宣言順)のルートが使用されます。
§逆ルーティング
ルーターは、Java の呼び出し内から URL を生成するために使用できます。これにより、すべての URI パターンを単一の設定ファイルに集中させることができるため、アプリケーションのリファクタリング時に自信を持つことができます。
routes ファイルで使用される各コントローラーに対して、ルーターは routes
パッケージ内に「リバースコントローラー」を生成します。これには、同じシグネチャを持つ同じアクションメソッドがありますが、play.mvc.Result
ではなく play.mvc.Call
を返します。
play.mvc.Call
は HTTP 呼び出しを定義し、HTTP メソッドと URI の両方を提供します。
たとえば、次のようなコントローラーを作成した場合
package controllers;
import play.*;
import play.mvc.*;
public class Application extends Controller {
public Result hello(String name) {
return ok("Hello " + name + "!");
}
}
そして、それを conf/routes
ファイルにマッピングした場合
# Hello action
GET /hello/:name controllers.Application.hello(name)
controllers.routes.Application
リバースコントローラーを使用することで、hello
アクションメソッドへの URL をリバースできます。
// Redirect to /hello/Bob
public Result index() {
return redirect(controllers.routes.Application.hello("Bob"));
}
注: 各コントローラーパッケージに
routes
サブパッケージがあります。したがって、controllers.Application.hello
アクションは、controllers.routes.Application.hello
を介してリバースできます(routes ファイル内で、生成されたパスに一致する他のルートがない場合に限ります)。
リバースアクションメソッドは非常にシンプルに動作します。パラメーターを受け取り、それらをルートパターンに代入します。パスセグメント(:foo
)の場合、値は代入される前にエンコードされます。正規表現とワイルドカードパターンの場合、値は複数のセグメントにまたがる可能性があるため、文字列は未加工の形式で代入されます。リバースルートに渡す際は、必要に応じてこれらのコンポーネントをエスケープし、検証されていないユーザー入力を渡さないようにしてください。
§相対ルート
絶対ルートの代わりに相対ルートを返すことが便利な場合があります。play.mvc.Call
によって返されるルートは常に絶対(先頭が /
)であり、HTTP プロキシ、ロードバランサー、API ゲートウェイによって Web アプリケーションへのリクエストが書き換えられると問題が発生する可能性があります。相対ルートを使用すると便利な例には、次のようなものがあります。
conf/routes
ファイルで構成されているものとは異なるものでルートをプレフィックスし、アプリケーションを予期していないルートにルート化する Web ゲートウェイの背後でアプリをホストする場合。- スタイルシートを動的にレンダリングする場合、アセットリンクが CDN によって異なる URL から提供される可能性があるため、相対的である必要があります。
相対ルートを生成できるようにするには、ターゲットルートを相対にする対象(開始ルート)を認識する必要があります。開始ルートは現在の RequestHeader
から取得できます。したがって、相対ルートを生成するには、現在の RequestHeader
または開始ルートを String
パラメーターとして渡す必要があります。
たとえば、次のようなコントローラーエンドポイントがある場合
package controllers;
import play.*;
import play.mvc.*;
public class Relative extends Controller {
public Result helloview(Http.Request request) {
ok(views.html.hello.render("Bob", request));
}
public Result hello(String name) {
return ok("Hello " + name + "!");
}
}
そして、それを conf/routes
ファイルにマッピングした場合
GET /foo/bar/hello controllers.Relative.helloview(request: Request)
GET /hello/:name controllers.Relative.hello(name)
リバースルーターを使用して以前と同様に相対ルートを定義し、relativeTo(play.mvc.RequestHeader requestHeader)
への追加呼び出しを含めることができます。
@(name: String, request: Http.RequestHeader)
<h1>Hello @name</h1>
<a href="@routes.Relative.hello(name)">Absolute Link</a>
<a href="@routes.Relative.hello(name).relativeTo(request)">Relative Link</a>
注: コントローラーから渡された
Http.Request
は、ビューパラメーターでHttp.RequestHeader
にキャストされます。
/foo/bar/hello
をリクエストすると、生成された HTML は次のようになります
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bob</title>
</head>
<body>
<a href="/hello/Bob">Absolute Link</a>
<a href="../../hello/Bob">Relative Link</a>
</body>
</html>
§デフォルトコントローラー
Play には、いくつかの便利なアクションを提供する Default
コントローラーが含まれています。これらは routes ファイルから直接呼び出すことができます。
# Redirects to https://play.dokyumento.jp/ with 303 See Other
GET /about controllers.Default.redirect(to = "https://play.dokyumento.jp/")
# Responds with 404 Not Found
GET /orders controllers.Default.notFound
# Responds with 500 Internal Server Error
GET /clients controllers.Default.error
# Responds with 501 Not Implemented
GET /posts controllers.Default.todo
この例では、GET /
は外部 Web サイトにリダイレクトしますが、別のアクション(上記の例の /posts
など)にリダイレクトすることも可能です。
§高度なルーティング
ルーティング DSLを参照してください。
次: HTTP 結果の操作
このドキュメントにエラーを見つけましたか?このページのソースコードは、こちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを遠慮なく送信してください。質問や共有するアドバイスがありますか?コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。