Spring 3.0 MVC绑定Enums区分大小写

dom*_*arr 53 java spring spring-mvc

如果我在Spring控制器中有一个RequestMapping,那么......

@RequestMapping(method = RequestMethod.GET, value = "{product}")
public ModelAndView getPage(@PathVariable Product product)
Run Code Online (Sandbox Code Playgroud)

而产品是一个枚举.例如.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
Run Code Online (Sandbox Code Playgroud)

有没有办法让枚举类型转换器了解小写主页实际上是Home?

我想保持url不区分大小写和我的Java枚举标准大写字母.

谢谢

public class ProductEnumConverter extends PropertyEditorSupport
{
    @Override public void setAsText(final String text) throws IllegalArgumentException
    {
        setValue(Product.valueOf(WordUtils.capitalizeFully(text.trim())));
    }
}
Run Code Online (Sandbox Code Playgroud)

注册它

<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>
Run Code Online (Sandbox Code Playgroud)

添加到需要特殊转换的控制器

@InitBinder
public void initBinder(WebDataBinder binder)
{
    binder.registerCustomEditor(Product.class, new ProductEnumConverter());
} 
Run Code Online (Sandbox Code Playgroud)

Gar*_*ryF 25

一般来说,您想要创建一个新的PropertyEditor来为您进行规范化,然后在Controller中注册它,如下所示:

@InitBinder
 public void initBinder(WebDataBinder binder) {

  binder.registerCustomEditor(Product.class,
    new CaseInsensitivePropertyEditor());
 }
Run Code Online (Sandbox Code Playgroud)

  • 对于Spring 3.2用户; 您现在可以使用`@ControllerAdvice`来注册全局init绑定器(以及其他内容).参见[参考指南](http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.2.html#new-in-3.2-webmvc-controller - 建议)了解更多信息. (5认同)
  • 不希望将此添加到使用此枚举的每个控制器.有全球解决方案吗? (2认同)

Sea*_*oyd 17

我认为你必须实现Custom PropertyEditor.

像这样的东西:

public class ProductEditor extends PropertyEditorSupport{

    @Override
    public void setAsText(final String text){
        setValue(Product.valueOf(text.toUpperCase()));
    }

}
Run Code Online (Sandbox Code Playgroud)

请参阅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);
}
Run Code Online (Sandbox Code Playgroud)


小智 15

也可以创建一个通用的转换器,它可以像这样使用所有的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(MyEnum.class, new CaseInsensitiveConverter<>(MyEnum.class));
}
Run Code Online (Sandbox Code Playgroud)

或者像skaffman解释的那样全球化


tst*_*tec 9

在Spring Boot 2中,您可以使用ApplicationConversionService。它提供了一些有用的转换器,尤其是org.springframework.boot.convert.StringToEnumIgnoringCaseConverterFactory-负责将字符串值转换为枚举实例的转换器。这是我设法找到的最通用的(我们不需要为每个枚举创建单独的转换器/格式化程序)和最简单的解决方案。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道问题与春季3有关,但这是Google在搜索spring mvc enums case insensitive短语时的第一个结果。


ska*_*man 7

要添加到@ 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>
Run Code Online (Sandbox Code Playgroud)

MyPropertyEditorRegistrar是一个实例PropertyEditorRegistrar,它依次PropertyEditor使用Spring 注册自定义对象.

简单地宣布这一点就足够了.