Рубрики
Без рубрики

Изучение сопоставления URL-адресов Spring 5 WebFlux

Узнайте о новых URL-адресах Spring 5.

Автор оригинала: baeldung.

1. Обзор

Весна 5 принесла новый Анализатор шаблонов путей для разбора шаблонов шаблонов URI . Это альтернатива ранее использованному AntPathMatcher .

AntPathMatcher был реализацией сопоставления шаблонов путей в стиле муравьев. Анализатор шаблонов путей разбивает путь на связанный список Элементов пути . Эта цепочка элементов Path берется классом Path Pattern для быстрого сопоставления шаблонов.

С помощью синтаксического анализатора Path Pattern также была введена поддержка нового синтаксиса переменной URI.

В этой статье мы рассмотрим новые/обновленные сопоставители шаблонов URL-адресов, представленные в Spring 5.0 WebFlux , а также те, которые были там с более старых версий Spring.

2. Новый шаблон URL-адреса соответствует весне 5.0

В выпуске Spring 5.0 добавлен очень простой в использовании синтаксис переменной URI: {*foo} для захвата любого количества сегментов пути в конце шаблона.

2.1. Синтаксис переменной URI {*foo} С использованием метода обработчика

Давайте рассмотрим пример шаблона переменной URI {*foo} другой пример с использованием @GetMapping и метода обработчика. Все, что мы дадим в пути после “/spring 5” , будет сохранено в переменной path “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} С использованием Функции Маршрутизатора

Давайте рассмотрим пример нового шаблона пути переменной URI с использованием функции Router :

private RouterFunction routingFunction() {
    return route(GET("/test/{*id}"), 
      serverRequest -> ok().body(fromValue(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/{*пути к файлам}”. В этом случае, если путь /files/hello.txt, значение переменной path “пути к файлам” будет “/hello.txt”, в то время как, если путь /files/test/test.txt, значение “пути к файлам” .

Наша функция маршрутизации для доступа к файловым ресурсам в каталоге /files/ :

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

Предположим, что ваши текстовые файлы hello.txt и test.txt содержат “привет” и “тест” соответственно. Это можно продемонстрировать с помощью тестового случая 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-адресов из предыдущих версий

Теперь давайте взглянем на все другие совпадения шаблонов URL-адресов, которые поддерживались более старыми версиями Spring. Все эти шаблоны работают как с функцией маршрутизатора , так и с методами обработчика с помощью @GetMapping .

3.1. “?” Соответствует Ровно Одному Символу

Если мы зададим шаблон пути как: “/t? st “, это будет соответствовать таким путям, как: “/тест” и “/вкус”, но не “/тест “ и “/тест”.

Пример кода, использующего функцию маршрутизатора и его тестовый случай JUnit:

private RouterFunction routingFunction() { 
    return route(GET("/t?st"), 
      serverRequest -> ok().body(fromValue("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”, это будет соответствовать шаблонам пути как: “/baeldung/Id”, “/baeldung/tutorialId”, “/baeldung/articleId” и т. Д:

private RouterFunction routingFunction() { 
    returnroute(
      GET("/baeldung/*Id"), 
      serverRequest -> ok().body(fromValue("/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 или более Сегментам пути До конца Пути

В этом случае сопоставление шаблонов не ограничивается одним сегментом пути. Если мы зададим шаблон как “/ресурсы/**”, он будет соответствовать всем путям к любому количеству сегментов пути после “/ресурсы/”:

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. Регулярное выражение ‘{baeldung:[a-z]+}’ в переменной Path

Мы также можем указать регулярное выражение для значения переменной path. Поэтому, если наш шаблон похож на “/{baeldung:[a-z]+}”, значением переменной path “baeldung” будет любой сегмент пути, соответствующий регулярному выражению gives:

private RouterFunction routingFunction() { 
    return route(GET("/{baeldung:[a-z]+}"), 
      serverRequest ->  ok()
        .body(fromValue("/{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}’ Несколько переменных пути в одном сегменте пути

Весна 5 убедилась, что несколько переменных пути будут разрешены в одном сегменте пути только при разделении разделителем. Только тогда Spring сможет различать две разные переменные пути:

private RouterFunction routingFunction() { 
 
    return route(
      GET("/{var1}_{var2}"),
      serverRequest -> ok()
        .body(fromValue( 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. Заключение

В этой статье мы рассмотрели новые совпадения URL-адресов в Spring 5, а также те, которые доступны в более старых версиях Spring.

Как всегда, реализацию всех примеров, которые мы обсуждали, можно найти на GitHub .