1概要

Spring 5は、URIテンプレートパターンを解析するためのhttps://jira.spring.io/browse/SPR-14544

PathPatternParser

をもたらしました

__.


これは、以前使用されていた

AntPathMatcher__の代わりになります。


AntPathMatcher

は、Antスタイルのパスパターンマッチングの実装でした。

PathPatternParser

は、パスを

PathElements

のリンクリストに分割します。

PathElements

のこのチェーンは、パターンの素早いマッチングのために

PathPattern

クラスによって使用されます。


PathPatternParser

では、新しいURI変数構文のサポートも導入されました。

この記事では、

Spring 5.0 WebFlux

で導入された新しい/更新されたURLパターンマッチャー、および以前のバージョンのSpring以降に存在したものを調べます。


2 Spring 5.0

の新しいURLパターンマッチャ

Spring 5.0リリースは非常に使いやすいURI変数の構文を追加しました:

パターンの末尾にあるパスセグメントをいくつでも取り込むには、\ {** foo}を使用します。


2.1. ハンドラメソッドを使用したURI変数の構文\ {

foo}

URI変数パターン

\ {** foo}

の例を見てみましょう


@ GetMapping

とハンドラーメソッドを使った別の例です。

“/spring5” __の後のパスに指定したものはすべて、パス変数“ id”に格納されます。

@GetMapping("/spring5/{** id}")
public String URIVariableHandler(@PathVariable String id) {
    return id;
}

@Test
public void whenMultipleURIVariablePattern__thenGotPathVariable() {

    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(fromObject(serverRequest.pathVariable("id"))));
}

この場合、 “/test”の後に書いたパスはすべてパス変数 “id”に取り込まれます。そのためのテストケースは次のようになります。

@Test
public void 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”

の値は “一方、パスが

/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 whenMultipleURIVariablePattern__thenGotPathVariable()
  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”

および_

“/teestは一致しません。 」


RouterFunction

を使用したコード例とそのJUnitテストケース

private RouterFunction<ServerResponse> routingFunction() {
    return route(GET("/t?st"),
      serverRequest -> ok().body(fromObject("Path/t?st is accessed")));
}

@Test
public void 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(fromObject("/baeldung/** Id path was accessed"))); }

@Test
public void 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 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:[a-z]}’

パス変数の正規表現

path変数の値に正規表現を指定することもできます。したがって、パターンが

“/\ {baeldung:[a-z]} “のような場合、パス変数

“ baeldung” __の値は、与えられた正規表現に一致するパスセグメントになります。

private RouterFunction<ServerResponse> routingFunction() {
    return route(GET("/{baeldung:[a-z]+}"),
      serverRequest ->  ok()
        .body(fromObject("/{baeldung:[a-z]+} was accessed and "
        + "baeldung=" + serverRequest.pathVariable("baeldung"))));
}

@Test
public void 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(fromObject( serverRequest.pathVariable("var1") + " , "
        + serverRequest.pathVariable("var2"))));
 }

@Test
public void whenGetMultiplePathVaribleInSameSegment__thenGotPathVariables()
  throws Exception {
      client.get()
        .uri("/baeldung__tutorial")
        .exchange()
        .expectStatus()
        .isOk()
        .expectBody(String.class)
        .isEqualTo("baeldung , tutorial");
}

4.まとめ

この記事では、Spring 5の新しいURLマッチャーと、古いバージョンのSpringで利用可能なURLマッチャーを調べました。

いつものように、私たちが議論したすべての例の実装はhttps://github.com/eugenp/tutorials/tree/master/spring-5-reactive[GitHubで動く]で見つけることができます。