Я отправляю names из простой веб-формы:
<form action = "test" method = "GET">
<select name = "names" multiple = "true">
<option>Doe, Jane</option>
<option>Doe, John</option>
</select>
<input type = "submit"/>
</form>
names привязан к List в контроллере:
@GetMapping("/test")
public String test(@RequestParam List<String> names, Model m) {
System.out.println(names.size());
System.out.println(names);
return "test";
}
Но поскольку значения моего имени содержат запятую (,), Spring анализирует то, что должно быть одним значением имени, на две строки.
Запрос GET для /test?names=Doe, John (удаление кодировки URL запятой от , до %2C для удобочитаемости) приводит к появлению списка, содержащего два значения String, Doe и John, а не одно значение Doe, John, как мне бы хотелось.
Однако при отправке нескольких значений, таких как: /test?names=Doe, Jane&names=Doe, John, все работает должным образом. В этом случае у меня есть список с двумя элементами: Doe, Jane и Doe, John.
Один из обходных путей — просто всегда отправлять пустое значение names в форму, включая:
<input type = "hidden" name = "names"/>
А затем удалить пустое значение из списка. Но я бы не хотел этого делать.
Как я могу настроить Spring MVC, чтобы НЕ анализировать строковые значения с использованием запятой, а вместо этого ожидать, что значения атрибутов списка будут просто повторяться, как ?name=Jon&name=Sue&name=Bob?
Я использую Spring Boot 2.3.2. Спасибо!
Преобразование, кажется, происходит в:
org.springframework.core.convert.support.StringToCollectionConverter
который должен быть конвертером по умолчанию, зарегистрированным фреймворком.
Вы можете использовать метод @InitBinder в контроллере или Controller Advice для регистрации конвертеров, однако я не уверен, как вы переопределяете или отключаете этот преобразователь по умолчанию.
Тогда проще всего вернуться к доступу к параметру непосредственно из HttpServletRequest:
@Controller
public class TestController {
@RequestMapping("/test")
public String test(@RequestParam("names") List<String> names, HttpServletRequest request) {
//1
System.out.println(request.getParameterValues("names").length);
System.out.println(Arrays.toString(request.getParameterValues("names")));
//2
System.out.println(names.size());
System.out.println(names);
return null;
}
}
После дополнительных экспериментов вы можете отключить вызов фреймворка StringToCollectionConverter в Spring Boot, явно удалив преобразование из String.class в Collection.class из GenericConversionService:
@Autowired
void conversionService(GenericConversionService genericConversionService) {
List<String> names = genericConversionService.convert("Ed, Al", List.class);
System.out.println(names.size()); // 2
genericConversionService.removeConvertible(String.class, Collection.class);
names = genericConversionService.convert("Ed, Al", List.class);
System.out.println(names.size()); // 1
}