Exploration de la correspondance des URL WebFlux du printemps 5

Explorer la correspondance des URL WebFlux du printemps 5

1. Vue d'ensemble

Spring 5 a apportéa newPathPatternParser pour analyser les modèles de modèles d'URI. Ceci est une alternative auxAntPathMatcher précédemment utilisés.

LeAntPathMatcher était une implémentation de la correspondance de modèle de chemin de style Ant. PathPatternParser divise le chemin en une liste chaînée dePathElements. Cette chaîne dePathElements est prise par la classePathPattern pour une correspondance rapide des motifs.

Avec lesPathPatternParser, la prise en charge d'une nouvelle syntaxe de variable URI a également été introduite.

Dans cet article,we’ll go through the new/updated URL pattern matchers introduced in Spring 5.0 WebFlux et aussi ceux qui existent depuis les anciennes versions de Spring.

2. Nouveaux filtreurs de modèles d'URL au printemps 5.0

La version Spring 5.0 a ajouté une syntaxe de variable URI très facile à utiliser: \ {* foo} pour capturer un nombre quelconque de segments de chemin à la fin du modèle.

2.1. Syntaxe de variable URI \ {* foo} Utilisation d'une méthode de gestionnaire

Voyons un exemple du modèle de variable URI\{*foo}, un autre exemple utilisant@GetMapping et une méthode de gestion. Tout ce que nous donnons dans le chemin après“/spring5” sera stocké dans la variable de chemin «id»:

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

    client.get()
      .uri("/spring5/example/tutorial")
      .exchange()
      .expectStatus()
      .is2xxSuccessful()
      .expectBody()
      .equals("/example/tutorial");

    client.get()
      .uri("/spring5/example")
      .exchange()
      .expectStatus()
      .is2xxSuccessful()
      .expectBody()
      .equals("/example");
}

2.2. Syntaxe de la variable URI \ {* foo} Utilisation deRouterFunction

Voyons un exemple du nouveau modèle de chemin de variable URI utilisantRouterFunction:

private RouterFunction routingFunction() {
    return route(GET("/test/{*id}"),
      serverRequest -> ok().body(fromObject(serverRequest.pathVariable("id"))));
}

Dans ce cas, le chemin que nous écrivons après “/ test” sera capturé dans la variable de chemin “id”. Donc, le cas de test pour cela pourrait être:

@Test
public void whenMultipleURIVariablePattern_thenGotPathVariable()
  throws Exception {

    client.get()
      .uri("/test/ab/cd")
      .exchange()
      .expectStatus()
      .isOk()
      .expectBody(String.class)
      .isEqualTo("/ab/cd");
}

2.3. Utilisation de la syntaxe de variable URI \ {* foo} pour accéder aux ressources

Si nous voulons accéder aux ressources, nous devrons écrire le modèle de chemin similaire à celui que nous avons écrit dans l'exemple précédent.

Supposons que notre modèle soit:“/files/\{*filepaths}”. Dans ce cas, si le chemin est/files/hello.txt,, la valeur de la variable de chemin“filepaths” sera «/hello.txt», alors que si le chemin est /files/test/test.txt, la valeur de“filepaths” = «/test/test.txt».

Notre fonction de routage pour accéder aux ressources de fichiers sous le répertoire/files/:

private RouterFunction routingFunction() {
    return RouterFunctions.resources(
      "/files/{*filepaths}",
      new ClassPathResource("files/")));
}

Supposons que nos fichiers textehello.txt ettest.txt contiennent respectivement“hello” et“test”. Cela peut être démontré avec un scénario de 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. Modèles d'URL existants des versions précédentes

Jetons maintenant un coup d'œil à tous les autres outils de correspondance de modèle d'URL compatibles avec les anciennes versions de Spring. Tous ces modèles fonctionnent avec les méthodesRouterFunction et Handler avec@GetMapping.

3.1. «?» Correspond exactement à un personnage

Si nous spécifions le modèle de chemin comme:“/t?st _ “, _ cela correspondra aux chemins comme:“/test” et“/tast”, mais pas“/tst” et“/teest”.

L'exemple de code utilisantRouterFunction et son cas de test JUnit:

private RouterFunction 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. ‘ correspond à 0 caractères ou plus dans un segment de chemin *

Si nous spécifions le modèle de chemin comme:“/example/*Id”,, cela correspondra aux modèles de cheminlike:”/example/Id”, “/example/tutorialId”, «/ exemple / articleId», etc:

private RouterFunction routingFunction() {
    returnroute(
      GET("/example/*Id"),
      serverRequest -> ok().body(fromObject("/example/*Id path was accessed"))); }

@Test
public void whenGetMultipleCharWildcard_thenGotPathPattern()
  throws Exception {
      client.get()
        .uri("/example/tutorialId")
        .exchange()
        .expectStatus()
        .isOk()
        .expectBody(String.class)
        .isEqualTo("/example/*Id path was accessed");
}

3.3. ‘ * 'correspond à 0 ou plusieurs segments de chemin jusqu'à la fin du chemin *

Dans ce cas, la correspondance de modèle n'est pas limitée à un seul segment de chemin. Si nous spécifions le modèle comme“/resources/**”,, il correspondra à tous les chemins vers n'importe quel nombre de segments de chemin après“/resources/”:

private RouterFunction 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. ‘\{example:[a-z]+}' Regex dans la variable de chemin

Nous pouvons également spécifier une expression rationnelle pour la valeur de la variable path. Donc, si notre modèle est comme“/\{example:[a-z]+}”,, la valeur de la variable de chemin“example” sera n'importe quel segment de chemin qui correspond à l'expression rationnelle donne:

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

@Test
public void whenGetRegexInPathVarible_thenGotPathVariable()
  throws Exception {

      client.get()
        .uri("/abcd")
        .exchange()
        .expectStatus()
        .isOk()
        .expectBody(String.class)
        .isEqualTo("/{example:[a-z]+} was accessed and "
          + "example=abcd");
}

3.5. ‘/{var1} {var2} '_ Variables de chemin multiples dans le même segment de chemin

Spring 5 a veillé à ce que plusieurs variables de chemin soient autorisées dans un segment de chemin unique uniquement lorsqu'elles sont séparées par un délimiteur. Alors seulement, Spring peut faire la distinction entre les deux variables de chemin différentes:

private RouterFunction 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("/example_tutorial")
        .exchange()
        .expectStatus()
        .isOk()
        .expectBody(String.class)
        .isEqualTo("example , tutorial");
}

4. Conclusion

Dans cet article, nous avons examiné les nouvelles correspondances d'URL du printemps 5, ainsi que celles disponibles dans les anciennes versions de Spring.

Comme toujours, l'implémentation de tous les exemples dont nous avons discuté peut être trouvéeover on GitHub.