Java Spring 3.0 MVC绑定枚举区分大小写
如果我在Spring控制器中有一个RequestMapping,就像这样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
@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);
}
}