Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring 3.0 MVC绑定枚举区分大小写_Java_Spring_Spring Mvc - Fatal编程技术网

Java Spring 3.0 MVC绑定枚举区分大小写

Java Spring 3.0 MVC绑定枚举区分大小写,java,spring,spring-mvc,Java,Spring,Spring Mvc,如果我在Spring控制器中有一个RequestMapping,就像这样 @RequestMapping(method = RequestMethod.GET, value = "{product}") public ModelAndView getPage(@PathVariable Product product) 产品是一个枚举。产品、家庭 当我请求页面时,mysite.com/home 我明白了 有没有办法让枚举类型转换器理解小写home实际上是home 我希望url不区分大小写,Ja

如果我在Spring控制器中有一个RequestMapping,就像这样

@RequestMapping(method = RequestMethod.GET, value = "{product}")
public ModelAndView getPage(@PathVariable Product product)
产品是一个枚举。产品、家庭

当我请求页面时,mysite.com/home

我明白了

有没有办法让枚举类型转换器理解小写home实际上是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>

广义地说,您希望创建一个新的PropertyEditor来为您进行规范化,然后在控制器中注册它,如下所示:

@InitBinder
 public void initBinder(WebDataBinder binder) {

  binder.registerCustomEditor(Product.class,
    new CaseInsensitivePropertyEditor());
 }
我想你必须这么做

大概是这样的:

public class ProductEditor extends PropertyEditorSupport{

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

}
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);
    }
}
请看如何绑定它

这里有一个更宽容的版本,以防在枚举常量中使用小写(您可能不应该这样做,但仍然如此):


要添加到@GaryF的答案中,并解决您对它的评论,您可以通过将全局自定义属性编辑器注入自定义
注释方法HandlerAdapter
来声明它们。SpringMVC通常默认注册其中一个,但是如果您选择,您可以给它一个特别配置的,例如

<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
的一个实例,它依次向Spring注册自定义
PropertyEditor
对象


仅声明这一点就足够了。

还可以创建一个通用转换器,该转换器将与所有枚举一起工作,如下所示:

public class ProductEditor extends PropertyEditorSupport{

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

}
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);
    }
}
公共类CaseInsensitiveConverter扩展属性编辑器支持{
私有最终类typeParameterClass;
公共案例不敏感转换程序(类类型参数类){
超级();
this.typeParameterClass=typeParameterClass;
}
@凌驾
public void setAsText(最终字符串文本)引发IllegalArgumentException{
String upper=text.toUpperCase();//或更健壮的东西
T值=T.valueOf(类型参数类,上限);
设置值(值);
}
}
用法:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(MyEnum.class, new CaseInsensitiveConverter<>(MyEnum.class));
}
@InitBinder
公共绑定器(WebDataBinder绑定器){
binder.registerCustomEditor(MyEnum.class,新的CaseInsensitiveConverter(MyEnum.class));
}

或者,正如skaffman在Spring Boot 2中解释的那样,您可以使用应用程序转换服务。它提供了一些有用的转换器,特别是
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);
    }
}


我知道问题是关于Spring 3的,但这是google在搜索
Spring mvc enum不区分大小写的短语时的第一个结果。

我不想把它添加到每个使用此enum的控制器中。有一个全球性的解决方案吗?@dom farr:有,但看起来skaffman已经击败了我。参见他的答案。对于Spring3.2用户;您现在可以使用
@ControllerAdvice
注册全局初始化绑定(以及其他内容)。有关详细信息,请参阅。@GaryF,所以我们不需要创建CustomEditorConfigurer bean?控制器通知中的init binder就足够了?它似乎不适用于
RequestBody
。有什么办法吗?似乎GenericConversionService.convert妨碍了这种类型的解决方案。@dom farr:是的,如果您使用
ConversionService
,您也需要这样做。是的,这是我第一次尝试的。它只是不起作用,所以我来到这里问了这个问题。也许我没有正确注册?我使用了ConversionServiceFactoryBean,但是正如我所说的,no go.Sean,我在spring boot上,并且在字符串映射到作为控制器参数的对象的枚举之后,似乎调用了initbinder方法。“我遗漏了什么吗?”AlexanderSuraphel见上面的评论。现在,ConversionService可能是默认启用的。实施定制converter@skaffman. 如果我删除所有控制器中的单个initBinder,似乎无法使其工作。不过我会继续挖掘这个。Thanks@dom:该方法确实有效,我自己使用,但我可能有一些细节wrong@skaffman. 也许这就是我的问题:@dom:是的,很好,这确实是个问题。您是否特别需要
?除非您使用的是Jackson/JSON映射,或者
@Valid
,否则您可能可以将其忽略。@skaffman。不幸的是,Jackson/JSON映射和@Valid被使用,这意味着我现在必须在每个控制器中使用@InitBinder。很好,我喜欢泛型类!它可能没有那么有效,但我更喜欢做一个equalsIgnoreCase,而不是你的toUpperCase+valueOf。getEnumConstants应该在typeParameterClass字段之外可用。要将此实现与@SeanPatrickFloydOn的方法结合起来,第二个想法是在每个请求上迭代枚举常量太痛苦了。我将在CaseInsensitiveConverter中粘贴一个HashMap以加速映射。Spring Boot中有类
RelaxedConversionService
StringToEnumIgnoringCaseConverterFactory
,但它们不是公共的。这里有一个使用
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);
    }
}