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 понимал, что дом с нижним регистром - это на самом деле Home?
Я бы хотел, чтобы регистр 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());
}
Ответы
Ответ 1
В общем, вы хотите создать новый PropertyEditor, который выполняет нормализацию для вас, а затем вы зарегистрируете это в своем контроллере следующим образом:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Product.class,
new CaseInsensitivePropertyEditor());
}
Ответ 2
Думаю, вам придётся реализовать пользовательский 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);
}
Ответ 3
Также возможно создать универсальный конвертер, который будет работать со всеми Enums следующим образом:
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));
}
Или глобально, как объясняет скаффман
Ответ 4
Чтобы добавить к ответу @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
с помощью Spring.
Просто объявление этого должно быть достаточно.