Связывание Spring 3.0 MVC перечисления чувствительны к регистру
Если у меня есть RequestMapping в контроллере Spring, как это...
@RequestMapping(method = RequestMethod.GET, value = "{product}")
public ModelAndView getPage(@PathVariable Product product)
И продукт это перечисление. например. Product.Home
Когда я запрашиваю страницу, mysite.com/home
я получил
Unable to convert value "home" from type 'java.lang.String' to type 'domain.model.product.Product'; nested exception is java.lang.IllegalArgumentException: No enum const class domain.model.product.Product.home
Есть ли способ, чтобы преобразователь типа enum понимал, что строчный дом - это действительно Дом?
Я хотел бы, чтобы URL-адрес не учитывал регистр, а мои Java-перечисления содержали стандартные заглавные буквы.
Спасибо
Решение
public class ProductEnumConverter extends PropertyEditorSupport
{
@Override public void setAsText(final String text) throws IllegalArgumentException
{
setValue(Product.valueOf(WordUtils.capitalizeFully(text.trim())));
}
}
регистрируя это
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="domain.model.product.Product" value="domain.infrastructure.ProductEnumConverter"/>
</map>
</property>
</bean>
Добавьте к контроллерам, которые нуждаются в специальном преобразовании
@InitBinder
public void initBinder(WebDataBinder binder)
{
binder.registerCustomEditor(Product.class, new ProductEnumConverter());
}
5 ответов
Вообще говоря, вы хотите создать новый PropertyEditor, который выполняет нормализацию за вас, и затем вы регистрируете это в вашем контроллере следующим образом:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Product.class,
new CaseInsensitivePropertyEditor());
}
Я думаю, вам придется реализовать Custom PropertyEditor.
Что-то вроде этого:
public class ProductEditor extends PropertyEditorSupport{
@Override
public void setAsText(final String text){
setValue(Product.valueOf(text.toUpperCase()));
}
}
Смотрите ответ GaryF о том, как его связать
Вот более терпимая версия, если вы используете строчные буквы в константах перечисления (что, вероятно, не следует, но все же):
@Override
public void setAsText(final String text){
Product product = null;
for(final Product candidate : Product.values()){
if(candidate.name().equalsIgnoreCase(text)){
product = candidate;
break;
}
}
setValue(product);
}
Также возможно создать универсальный конвертер, который будет работать со всеми перечислениями следующим образом:
public class CaseInsensitiveConverter<T extends Enum<T>> extends PropertyEditorSupport {
private final Class<T> typeParameterClass;
public CaseInsensitiveConverter(Class<T> typeParameterClass) {
super();
this.typeParameterClass = typeParameterClass;
}
@Override
public void setAsText(final String text) throws IllegalArgumentException {
String upper = text.toUpperCase(); // or something more robust
T value = T.valueOf(typeParameterClass, upper);
setValue(value);
}
}
Использование:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(MyEnum.class, new CaseInsensitiveConverter<>(MyEnum.class));
}
Или глобально, как объясняет Скаффман
В Spring Boot 2 вы можете использовать ApplicationConversionService
, Он предоставляет некоторые полезные конвертеры, особенно org.springframework.boot.convert.StringToEnumIgnoringCaseConverterFactory
- отвечает за преобразование строкового значения в экземпляр enum. Это самое общее (нам не нужно создавать отдельный конвертер / форматтер для каждого перечисления) и самое простое решение, которое мне удалось найти.
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class AppWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
ApplicationConversionService.configure(registry);
}
}
Я знаю, что вопросы касаются Spring 3, но это первый результат в Google при поиске spring mvc enums case insensitive
фраза.
Чтобы добавить ответ @GaryF и добавить к нему свой комментарий, вы можете объявить глобальные редакторы пользовательских свойств, вставив их в пользовательские AnnotationMethodHandlerAdapter
, Spring MVC обычно регистрирует один из них по умолчанию, но вы можете назначить его специально настроенным, например, например,
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.xyz.MyPropertyEditorRegistrar"/>
</list>
</property>
</bean>
</property>
</bean>
MyPropertyEditorRegistrar
это пример PropertyEditorRegistrar
, который в свою очередь регистрирует обычай PropertyEditor
объекты с весны.
Простого объявления этого должно быть достаточно.