JavaでのPlayアプリケーションのルーティング
1. 概要
ルーティングは、 SpringMVCを含むほとんどのWeb開発フレームワークに見られる一般的な概念です。
ルートは、ハンドラーにマップされるURLパターンです。 ハンドラーは、Webアプリケーションのダウンロード可能なアセットなどの物理ファイル、またはMVCアプリケーションのコントローラーなどの要求を処理するクラスにすることができます。
このチュートリアルでは、 PlayFrameworkを使用してWebアプリケーションを開発する際のルーティングの側面について説明します。
2. 設定
まず、JavaPlayアプリケーションを作成する必要があります。 マシン上でPlayFrameworkをセットアップする方法の詳細は、紹介記事にあります。
セットアップが完了するまでに、ブラウザーからアクセスできるPlayアプリケーションが機能するようになります。
3. HTTPルーティング
では、HTTPリクエストを送信するたびに、Playはどのコントローラーを参照するかをどのように知るのでしょうか。 この質問に対する答えは、 app / conf /routers構成ファイルにあります。
Playのルーターは、HTTPリクエストをアクションコールに変換します。 HTTPリクエストはMVCアーキテクチャのイベントと見なされ、ルーターは routers ファイルを参照して、どのコントローラーとそのコントローラーでどのアクションを実行するかを調べます。
これらの各イベントは、ルーターに2つのパラメーターを提供します。1つはクエリ文字列を含む要求パス、もう1つは要求のHTTPメソッドです。
4. Playを使用した基本的なルーティング
ルーターが機能するためには、 conf / routers ファイルで、HTTPメソッドとURIパターンの適切なコントローラーアクションへのマッピングを定義する必要があります。
GET / controllers.HomeController.index
GET / assets/*file controllers.Assets.versioned(path="/public", file: Asset)
すべてのルートファイルは、 /Assetsエンドポイントのクライアントが使用できるplay-routing/publicフォルダー内の静的リソースもマップする必要があります。 HTTPルートを定義する構文と、HTTPメソッド spaceURIパターンspaceコントローラーアクションに注意してください。
5. URIパターン
このセクションでは、URIパターンについて少し説明します。
5.1. 静的URIパターン
上記の最初の3つのURIパターンは静的です。 これは、URLのリソースへのマッピングが、コントローラーアクションでそれ以上処理されることなく行われることを意味します。
コントローラメソッドが呼び出されている限り、リクエストの前にコンテンツが決定された静的リソースを返します。
5.2. 動的URIパターン
上記の最後のURIパターンは動的です。 これは、これらのURIでリクエストを処理するコントローラーアクションが、レスポンスを決定するためにリクエストからの情報を必要とすることを意味します。 上記の場合、ファイル名が必要です。
イベントの通常のシーケンスは、ルーターがイベントを受信し、URLからパスを選択し、そのセグメントをデコードして、それらをコントローラーに渡すことです。
次に、パスとクエリのパラメーターがパラメーターとしてコントローラーアクションに挿入されます。 次のセクションの例でこれを示します。
6. Playによる高度なルーティング
このセクションでは、動的URIパターンを使用したルーティングの高度なオプションについて詳しく説明します。
6.1. 単純なパスパラメータ
シンプルパスパラメーターは、ホストとポートの後に表示され、出現順に解析される、リクエストURL内の名前のないパラメーターです。
play-routing / app /HomeController。java内で、新しいアクションを作成しましょう。
public Result greet(String name) {
return ok("Hello " + name);
}
リクエストURLからパスパラメータを選択し、それを変数名にマップできるようにする必要があります。
ルーターは、ルート構成からこれらの値を取得します。
それでは、 play-routing / conf / routers を開いて、この新しいアクションのマッピングを作成しましょう。
GET /greet/:name controllers.HomeController.greet(name: String)
名前がコロン構文の動的パスセグメントであることをルーターに通知し、それをパラメーターとしてgreetアクション呼び出しに渡す方法に注目してください。
それでは、ブラウザに http:// locahost:9000 / greet / john をロードしてみましょう。名前が表示されます:
Hello john
アクションパラメータが文字列タイプの場合、パラメータタイプを指定せずにアクション呼び出し中に渡すことがありますが、これは他のタイプでは同じではありません。
/greetエンドポイントに年齢情報を追加してみましょう。
HomeController の挨拶アクションに戻り、次のように変更します。
public Result greet(String name, int age) {
return ok("Hello " + name + ", you are " + age + " years old");
}
そしてへのルート:
GET /greet/:name/:age controllers.HomeController.greet(name: String, age: Integer)
変数age:Integerを宣言するためのScala構文にも注意してください。 Javaでは、 Integerage構文を使用します。 PlayFrameworkはScalaに組み込まれています。 その結果、多くのscala構文があります。
http:// localhost:9000 / greet / john / 26 をロードしましょう:
Hello john, you are 26 years old
6.2. パスパラメータのワイルドカード
ルート構成ファイルでは、最後のマッピングは次のとおりです。
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
パスの動的な部分でワイルドカードを使用します。 Playに伝えているのは、実際のリクエストで * file を置き換える値はすべて全体として解析され、他のパスパラメータの場合のようにデコードされないようにする必要があるということです。
この例では、コントローラーは組み込みの Assets であり、クライアントが play-routing /publicフォルダーからファイルをダウンロードできるようにします。 http:// localhost:9000 / asset / images / favicon.png をロードすると、
HomeController。javaで独自のサンプルアクションを作成しましょう。
public Result introduceMe(String data) {
String[] clientData = data.split(",");
return ok("Your name is " + clientData[0] + ", you are " + clientData[1] + " years old");
}
このアクションでは、1つのStringパラメーターを受け取り、それをデコードするためにロジックを適用していることに注意してください。 この場合のロジックは、コンマ区切りのStringを配列に分割することです。 以前は、このデータをデコードするためにルーターに依存していました。
ワイルドカードを使用すると、私たちは自分自身でいます。 このデータをに渡すときに、クライアントが構文を正しく取得することを期待しています。 理想的には、入力文字列を使用する前に検証する必要があります。
このアクションへのルートを作成しましょう:
GET /*data controllers.HomeController.introduceMe(data)
次に、URL http:// localhost:9000 / john、26をロードします。 これは印刷されます:
Your name is john, you are 26 years old
6.3. パスパラメータの正規表現
ワイルドカードと同様に、動的部分には正規表現を使用できます。 数値を受け取り、その正方形を返すアクションを追加しましょう。
public Result squareMe(Long num) {
return ok(num + " Squared is " + (num * num));
}
次に、そのルートを追加します。
GET /square/$num<[0-9]+> controllers.HomeController.squareMe(num:Long)
このルートをintroduceMeルートの下に配置して、新しい概念を紹介しましょう。 このルーティング構成では、正規表現部分が正の整数であるルートのみを処理できます。
前の段落で説明したようにルートを配置し、 http:// localhost:9000 / square / 2 をロードすると、ArrayIndexOutOfBoundsExceptionが表示されます。
サーバーコンソールでエラーログを確認すると、アクション呼び出しがsquareMeアクションではなくintroduceMeアクションで実際に実行されたことがわかります。 ワイルドカードについて前に述べたように、私たちは私たち自身であり、受信データを検証しませんでした。
カンマ区切りの文字列の代わりに、IntroductionMeメソッドが文字列「square/2」で呼び出されました。 その結果、それを分割した後、サイズ1の配列を取得しました。 インデックス1に到達しようとすると、例外がスローされました。
当然、呼び出しはsquareMeメソッドにルーティングされると予想されます。 なぜintroduceMeにルーティングされたのですか? その理由は、次に説明するルーティング優先度と呼ばれる再生機能です。
7. ルーティングの優先順位
squareMeとintroduceMeの間にあるようにルート間に競合がある場合、Playは宣言順序の最初のルートを選択します。
なぜ競合があるのですか? ワイルドカードコンテキストパス/* data は、ベースパス/以外のすべてのリクエストURLと一致するためです。 したがって、 URIパターンがワイルドカードを使用するすべてのルートは、最後に表示される必要があります。
次に、IntroductionMeルートがsquareMeの後に来るようにルートの宣言順序を変更して、リロードします。
2 Squared is 4
ルート内の正規表現の能力をテストするには、 http:// locahost:9000 / square / -1 をロードしてみてください。ルーターは、squareMeルートと一致しません。 代わりに、 IntroductionMe、と一致し、ArrayIndexOutOfBoundsExceptionを再度取得します。
これは、 -1 が提供された正規表現と一致せず、アルファベット文字も一致しないためです。
8. パラメーター
ここまでは、routesファイルでパラメータタイプを宣言するための構文について説明してきました。
このセクションでは、ルートのパラメータを処理するときに使用できるその他のオプションについて説明します。
8.1. 固定値のパラメーター
パラメータに固定値を使用したい場合があります。 これは、提供されたパスパラメータを使用するようにPlayに指示する方法です。または、リクエストコンテキストがパス / の場合は、特定の固定値を使用します。
別の見方をすると、同じコントローラーアクションにつながる2つのエンドポイントまたはコンテキストパスがあります。一方のエンドポイントはリクエストURLからのパラメーターを必要とし、そのパラメーターがない場合はデフォルトでもう一方のエンドポイントになります。
これを示すために、 writer()アクションをHomeControllerに追加しましょう。
public Result writer() {
return ok("Routing in Play by Baeldung");
}
APIがStringを返すことを常に望んでいないと仮定します。
Routing in Play by Baeldung
リクエストにauthorパラメータがない場合にのみ、デフォルトで固定値 Baeldung に設定して、リクエストと一緒に記事の作成者の名前を送信することで制御します。
それでは、パラメータを追加して、writerアクションをさらに変更しましょう。
public Result writer(String author) {
return ok("REST API with Play by " + author);
}
ルートに固定値パラメーターを追加する方法も見てみましょう。
GET /writer controllers.HomeController.writer(author = "Baeldung")
GET /writer/:author controllers.HomeController.writer(author: String)
1つではなくHomeController.indexアクションにつながる2つの別々のルートがあることに注意してください。
ブラウザからhttp:// localhost:9000 / writer をロードすると、次のようになります。
Routing in Play by Baeldung
そして、 http:// localhost:9000 / writer / john をロードすると、次のようになります。
Routing in Play by john
8.2. デフォルト値のパラメータ
固定値の他に、パラメータにはデフォルト値を設定することもできます。 どちらも、要求が必要な値を提供しない場合に備えて、コントローラーのアクションパラメーターにフォールバック値を提供します。
2つの違いは、固定値がパスパラメータのフォールバックとして使用されるのに対し、デフォルト値はクエリパラメータのフォールバックとして使用されることです。
パスパラメータの形式はhttp:// localhost:9000 / param1 / param2 で、クエリパラメータの形式は
2つ目の違いは、ルートで2つを宣言する構文にあります。 固定値パラメーターは、次のように代入演算子を使用します。
author = "Baeldung"
デフォルト値は異なるタイプの割り当てを使用しますが、
author ?= "Baeldung"
author に値が含まれていないことが判明した場合に、 Baeldungをauthorに条件付きで割り当てる?=演算子を使用します。
完全なデモンストレーションを行うために、HomeController.writerアクションを作成しましょう。 たとえば、パスパラメータである作成者の名前とは別に、作成者 id をクエリパラメータとして渡します。リクエストで渡されない場合は、デフォルトで1になります。
writerアクションを次のように変更します。
public Result writer(String author, int id) {
return ok("Routing in Play by: " + author + " ID: " + id);
}
ライターは次の場所にルーティングします。
GET /writer controllers.HomeController.writer(author="Baeldung", id: Int ?= 1)
GET /writer/:author controllers.HomeController.writer(author: String, id: Int ?= 1)
http:// localhost:9000 / writer を読み込んでいます。次のように表示されます:
Routing in Play by: Baeldung ID: 1
http:// localhost:9000 / writer?id = 10 を押すと、次のようになります。
Routing in Play by: Baeldung ID: 10
http:// localhost:9000 / writer / john はどうですか?
Routing in Play by: john ID: 1
そして最後に、 http:// localhost:9000 / writer / john?id =5は次を返します。
Routing in Play by: john ID: 5
9. 結論
この記事では、Playアプリケーションでのルーティングの概念について説明しました。 また、 Play Frameworkを使用したRESTfulAPIの構築に関する記事もあり、このチュートリアルのルーティングの概念が実際の例に適用されています。
いつものように、このチュートリアルのソースコードはGitHubでから入手できます。