Подтвердить что ты не робот

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());
} 
4b9b3361

Ответ 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.

Просто объявление этого должно быть достаточно.