Spring5WebFluxURLマッチングの調査
1. 概要
春5がもたらした新しい PathPatternParser URIテンプレートパターンの解析用
AntPathMatcher は、Antスタイルのパスパターンマッチングの実装でした。 PathPatternParser は、パスをPathElementsのリンクリストに分割します。 このPathElementsのチェーンは、パターンの迅速なマッチングのためにPathPatternクラスによって取得されます。
PathPatternParser では、新しいURI変数構文のサポートも導入されました。
この記事では、 Spring 5.0 WebFlux で導入された新しい/更新されたURLパターンマッチャーと、Springの古いバージョン以降に存在していたものについて説明します。
2. Spring5.0の新しいURLパターンマッチャー
Spring 5.0リリースでは、非常に使いやすいURI変数構文{* foo}が追加され、パターンの最後にある任意の数のパスセグメントをキャプチャします。
2.1. URI変数構文{*foo}ハンドラーメソッドの使用
URI変数pattern{*foo}の例を見てみましょう。@GetMappingとハンドラーメソッドを使用した別の例です。 「/spring5」の後にパスに指定したものはすべて、パス変数「id」に格納されます。
@GetMapping("/spring5/{*id}")
public String URIVariableHandler(@PathVariable String id) {
return id;
}
@Test
public void givenHandlerMethod_whenMultipleURIVariablePattern_then200() {
client.get()
.uri("/spring5/baeldung/tutorial")
.exchange()
.expectStatus()
.is2xxSuccessful()
.expectBody()
.equals("/baeldung/tutorial");
client.get()
.uri("/spring5/baeldung")
.exchange()
.expectStatus()
.is2xxSuccessful()
.expectBody()
.equals("/baeldung");
}
2.2. URI変数構文{*foo}RouterFunctionの使用
RouterFunctionを使用した新しいURI可変パスパターンの例を見てみましょう。
private RouterFunction<ServerResponse> routingFunction() {
return route(GET("/test/{*id}"),
serverRequest -> ok().body(fromValue(serverRequest.pathVariable("id"))));
}
この場合、「/ test」の後に書き込むパスはすべて、パス変数「id」にキャプチャされます。 したがって、そのテストケースは次のようになります。
@Test
public void givenRouter_whenMultipleURIVariablePattern_thenGotPathVariable()
throws Exception {
client.get()
.uri("/test/ab/cd")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("/ab/cd");
}
2.3. リソースにアクセスするためのURI変数構文{*foo}の使用
リソースにアクセスする場合は、前の例で記述したのと同様のパスパターンを記述する必要があります。
したがって、パターンが次のようになっているとします。“ / files / {* filepaths}”。この場合、パスが /files/hello.txtの場合、パス変数の値「filepaths」は「/hello.txt」になりますが、パスが /files/test/test.txtの場合、「filepaths」の値=「/test/test.txt」。
/ files /ディレクトリの下のファイルリソースにアクセスするためのルーティング機能:
private RouterFunction<ServerResponse> routingFunction() {
return RouterFunctions.resources(
"/files/{*filepaths}",
new ClassPathResource("files/")));
}
テキストファイルhello.txtとtest.txtにそれぞれ「hello」と「test」が含まれていると仮定します。 これは、JUnitテストケースで実証できます。
@Test
public void givenResources_whenAccess_thenGot()
throws Exception {
client.get()
.uri("/files/test/test.txt")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("test");
client.get()
.uri("/files/hello.txt")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("hello");
}
3. 以前のバージョンの既存のURLパターン
ここで、古いバージョンのSpringでサポートされている他のすべてのURLパターンマッチャーを見てみましょう。 これらのパターンはすべて、RouterFunctionメソッドと@GetMappingのHandlerメソッドの両方で機能します。
3.1. 「?」 正確に1つの文字に一致します
パスパターンを“ / t? st “、と指定すると、“ / test”および“/tastのようなパスに一致します。 ”、ですが、“ / tst”および“ / teast”ではありません。
RouterFunction とそのJUnitテストケースを使用したサンプルコード:
private RouterFunction<ServerResponse> routingFunction() {
return route(GET("/t?st"),
serverRequest -> ok().body(fromValue("Path /t?st is accessed")));
}
@Test
public void givenRouter_whenGetPathWithSingleCharWildcard_thenGotPathPattern()
throws Exception {
client.get()
.uri("/test")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Path /t?st is accessed");
}
3.2. ‘*’はパスセグメント内の0個以上の文字に一致します
パスパターンを:“ / baeldung / * Id”、と指定すると、パスパターン like:” / baeldung / Id”、“ / baeldung / tutorialId”、“と一致します。 / baeldung / articleId」など:
private RouterFunction<ServerResponse> routingFunction() {
returnroute(
GET("/baeldung/*Id"),
serverRequest -> ok().body(fromValue("/baeldung/*Id path was accessed"))); }
@Test
public void givenRouter_whenGetMultipleCharWildcard_thenGotPathPattern()
throws Exception {
client.get()
.uri("/baeldung/tutorialId")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("/baeldung/*Id path was accessed");
}
3.3. ‘**’は、パスの終わりまで0個以上のパスセグメントに一致します
この場合、パターンマッチングは単一のパスセグメントに限定されません。 パターンを“ / resources / **”、と指定すると、“ / resources /”:以降の任意の数のパスセグメントにすべてのパスが一致します。
private RouterFunction<ServerResponse> routingFunction() {
return RouterFunctions.resources(
"/resources/**",
new ClassPathResource("resources/")));
}
@Test
public void givenRouter_whenAccess_thenGot() throws Exception {
client.get()
.uri("/resources/test/test.txt")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("content of file test.txt");
}
3.4. ‘{baeldung:[az]+}’パス変数の正規表現
パス変数の値に正規表現を指定することもできます。 したがって、パターンが“ / {baeldung:[az] +}”のような場合、パス変数“ baeldung” の値は、指定された正規表現に一致する任意のパスセグメントになります。
private RouterFunction<ServerResponse> routingFunction() {
return route(GET("/{baeldung:[a-z]+}"),
serverRequest -> ok()
.body(fromValue("/{baeldung:[a-z]+} was accessed and "
+ "baeldung=" + serverRequest.pathVariable("baeldung"))));
}
@Test
public void givenRouter_whenGetRegexInPathVarible_thenGotPathVariable()
throws Exception {
client.get()
.uri("/abcd")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("/{baeldung:[a-z]+} was accessed and "
+ "baeldung=abcd");
}
3.5. ‘/ {var1} _{var2}’同じパスセグメント内の複数のパス変数
Spring 5では、区切り文字で区切られた場合にのみ、単一のパスセグメントで複数のパス変数が許可されるようになりました。 そうして初めて、Springは2つの異なるパス変数を区別できます。
private RouterFunction<ServerResponse> routingFunction() {
return route(
GET("/{var1}_{var2}"),
serverRequest -> ok()
.body(fromValue( serverRequest.pathVariable("var1") + " , "
+ serverRequest.pathVariable("var2"))));
}
@Test
public void givenRouter_whenGetMultiplePathVaribleInSameSegment_thenGotPathVariables()
throws Exception {
client.get()
.uri("/baeldung_tutorial")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("baeldung , tutorial");
}
4. 結論
この記事では、Spring 5の新しいURLマッチャーと、古いバージョンのSpringで使用可能なURLマッチャーについて説明しました。
いつものように、ここで説明したすべての例の実装は、GitHubのにあります。