spring boot 枚举使用的坑整理
java枚举的功能挺多,但是坑更多,使用的时候要注意。如下面这个枚举。
@Getter @AllArgsConstructor publicenumEnumExpenseTypeimplementsBaseEnum{ 小欢喜(1), 大欢喜(2); privatefinalintvalue; }
咋一看,没什么问题,但是具体使用过程中,总是会出问题。原因就是这个枚举没有按照从0开始索引,除此之外即使从0开始,中间有断的索引也会有问题。主要出现在以下方面:
1.在controller的方法中,比如以这个枚举为参数,如下代码:
@RequestMapping("/**") publicStringgetRejectReasons(EnumExpenseTypetype){ return""; }
前台传入的参数如果是type:1,那它值应该是:小欢喜,实际上呢?
Causedby:java.lang.IllegalArgumentException:Noenumconstantcom.**.EnumReasonType.1 atjava.lang.Enum.valueOf(Enum.java:238)~[?:1.8.0_111] atorg.springframework.core.convert.support.StringToEnumConverterFactory$StringToEnum.convert(StringToEnumConverterFactory.java:52)~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE] atorg.springframework.core.convert.support.StringToEnumConverterFactory$StringToEnum.convert(StringToEnumConverterFactory.java:38)~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE] atorg.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:436)~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE] atorg.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE] atorg.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191)~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE] atorg.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:129)~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE] atorg.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73)~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE] atorg.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:53)~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE] atorg.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:693)~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE] atorg.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:124)~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE] ...81more
Failedtoconvertvalueoftype'java.lang.String'torequiredtype'com.**.EnumExpenseType';
nestedexceptionisorg.springframework.core.convert.ConversionFailedException:
Failedtoconvertfromtype[java.lang.String]totype[com.**.EnumExpenseType]forvalue'1';
nestedexceptionisjava.lang.IllegalArgumentException:Noenumconstantcom.***.EnumExpenseType.1
实际上它却报了个错。转换失败了。
查看报错信息,可以定位到是spring框架中StringToEnumConverterFactory中转换失败,具体代码如下:
privatestaticclassStringToEnumimplementsConverter { privatefinalClass enumType; publicStringToEnum(Class enumType){ this.enumType=enumType; } @Override publicTconvert(Stringsource){ if(source.isEmpty()){ //It'sanemptyenumidentifier:resettheenumvaluetonull. returnnull; } return(T)Enum.valueOf(this.enumType,source.trim()); } }
是Enum.valueOf这里报错,Enum.valueOf的后面的值并不是我们的value,而是name(这里的小欢喜)。
所以,我们不能使用这个spring提供converter,需要自定义一个:StringToEnumConverterFactory
publicclassStringToEnumConverterFactoryimplementsConverterFactory{ privatestaticfinalMap converterMap=newHashMap<>(); @Override public Converter getConverter(Class targetType){ Converter converter=converterMap.get(targetType); if(converter==null){ converter=newStringToEnumConverter<>(targetType); converterMap.put(targetType,converter); } returnconverter; } classStringToEnumConverter implementsConverter { privateMap enumMap=newHashMap<>(); StringToEnumConverter(Class enumType){ T[]enums=enumType.getEnumConstants(); for(Te:enums){ enumMap.put(String.valueOf(e.getValue()),e); } } @Override publicTconvert(Stringsource){ Tt=enumMap.get(source); if(t==null){ //异常可以稍后去捕获 thrownewIllegalArgumentException("Noelementmatches"+source); } returnt; } } }
然后再将这个工厂配置到项目中WebMvcConfigurationSupport:
@Override publicvoidaddFormatters(FormatterRegistryregistry){ registry.addConverterFactory(newStringToEnumConverterFactory()); }
意思就是string转BaesEnum都走这个converter。
至此这个坑就算解决了。
以上就是本次介绍的全部知识点内容,感谢大家对毛票票的支持。