Перейти к основному содержимому

Spring MVC @PathVariable с точкой (.) усекается

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы обсудим распространенную проблему при работе с Spring MVC — при использовании Spring @PathVariable с @RequestMapping для сопоставления конца URI запроса, содержащего точку, мы получим частичное значение. в нашей переменной, усеченной до последней точки.

В следующих разделах мы сосредоточимся на том, почему это происходит и как изменить это поведение.

Введение в Spring MVC можно найти в этой статье .

2. Нежелательная помощь Spring

Фреймворк часто вызывает такое нежелательное поведение из-за того, как он интерпретирует переменную пути.

В частности, Spring считает, что все, что стоит за последней точкой, является расширением файла, таким как .json или .xml.

В результате он усекает значение для получения параметра.

Давайте посмотрим на пример использования переменных пути, а затем проанализируем результат с различными возможными значениями:

@RestController
public class CustomController {
@GetMapping("/example/{firstValue}/{secondValue}")
public void example(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
// ...
}
}

В приведенном выше примере давайте рассмотрим следующие запросы и оценим наши переменные:

  • пример URL /галерея/ссылка приводит к оценке firstValue = «gallery» и secondValue = «link»
  • при использовании URL-адреса example/gallery.df/link.ar у нас будет firstValue = «gallery.df» и secondValue = «link»
  • с URL-адресом example/gallery.df/link.com.ar наши переменные будут: firstValue = «gallery.df» и secondValue = «link.com»

Как мы видим, первая переменная не затрагивается, но вторая всегда усекается.

3. Решения

Один из способов решить это неудобство — изменить наше определение @PathVariable , добавив отображение регулярного выражения . Таким образом, любая точка, включая последнюю, будет считаться частью нашего параметра:

@GetMapping("/example/{firstValue}/{secondValue:.+}")   
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}

Другой способ избежать этой проблемы — добавить косую черту в конце @PathVariable . Это будет заключать в себя нашу вторую переменную, защищая ее от поведения Spring по умолчанию:

@GetMapping("/example/{firstValue}/{secondValue}/")

Два приведенных выше решения применяются к одному сопоставлению запросов, которое мы модифицируем.

Если мы хотим изменить поведение на глобальном уровне MVC, нам нужно предоставить пользовательскую конфигурацию . Для этой цели мы можем расширить WebMvcConfigurationSupport и переопределить его метод getPathMatchConfigurer() для настройки PathMatchConfigurer .

@Configuration
public class CustomWebMvcConfigurationSupport extends WebMvcConfigurationSupport {

@Override
protected PathMatchConfigurer getPathMatchConfigurer() {
PathMatchConfigurer pathMatchConfigurer = super.getPathMatchConfigurer();
pathMatchConfigurer.setUseSuffixPatternMatch(false);

return pathMatchConfigurer;
}
}

Мы должны помнить, что этот подход влияет на все URL-адреса.

С этими тремя вариантами мы получим один и тот же результат: при вызове URL-адреса example/gallery.df/link.com.ar наша переменная secondValue будет оцениваться как «link.com.ar», что нам и нужно.

3.1. Уведомление об устаревании

Начиная с Spring Framework 5.2.4 метод setUseSuffixPatternMatch (boolean) устарел, чтобы не поощрять использование расширений пути для маршрутизации запросов и согласования контента. По сути, текущая реализация затрудняет защиту веб-приложений от атаки отраженной загрузки файлов (RFD) .

Кроме того, начиная с Spring Framework 5.3, сопоставление шаблонов суффиксов будет работать только для явно зарегистрированных суффиксов, чтобы предотвратить произвольные расширения.

Суть в том, что с Spring 5.3 нам не нужно будет использовать setUseSuffixPatternMatch(false) , так как он отключен по умолчанию.

4. Вывод

В этом кратком обзоре мы рассмотрели различные способы решения распространенной проблемы при работе с @PathVariable и @RequestMapping в Spring MVC и источник этой проблемы.

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