«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/галерея /link приводит к оценке 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.