spring boot 枚举使用的坑整理
java 枚举的功能挺多,但是坑更多,使用的时候要注意。如下面这个枚举。
@getter @allargsconstructor public enum enumexpensetype implements baseenum { 小欢喜(1), 大欢喜(2); private final int value; }
咋一看,没什么问题,但是具体使用过程中,总是会出问题。原因就是这个枚举没有按照从0开始索引,除此之外即使从0开始,中间有断的索引也会有问题。主要出现在以下方面:
1. 在controller的方法中,比如以这个枚举为参数,如下代码:
@requestmapping("/**") public string getrejectreasons(enumexpensetype type) { return ""; }
前台传入的参数如果是type:1, 那它值应该是:小欢喜,实际上呢?
caused by: java.lang.illegalargumentexception: no enum constant com.**.enumreasontype.1 at java.lang.enum.valueof(enum.java:238) ~[?:1.8.0_111] at org.springframework.core.convert.support.stringtoenumconverterfactory$stringtoenum.convert(stringtoenumconverterfactory.java:52) ~[spring-core-5.1.8.release.jar:5.1.8.release] at org.springframework.core.convert.support.stringtoenumconverterfactory$stringtoenum.convert(stringtoenumconverterfactory.java:38) ~[spring-core-5.1.8.release.jar:5.1.8.release] at org.springframework.core.convert.support.genericconversionservice$converterfactoryadapter.convert(genericconversionservice.java:436) ~[spring-core-5.1.8.release.jar:5.1.8.release] at org.springframework.core.convert.support.conversionutils.invokeconverter(conversionutils.java:41) ~[spring-core-5.1.8.release.jar:5.1.8.release] at org.springframework.core.convert.support.genericconversionservice.convert(genericconversionservice.java:191) ~[spring-core-5.1.8.release.jar:5.1.8.release] at org.springframework.beans.typeconverterdelegate.convertifnecessary(typeconverterdelegate.java:129) ~[spring-beans-5.1.7.release.jar:5.1.7.release] at org.springframework.beans.typeconvertersupport.convertifnecessary(typeconvertersupport.java:73) ~[spring-beans-5.1.7.release.jar:5.1.7.release] at org.springframework.beans.typeconvertersupport.convertifnecessary(typeconvertersupport.java:53) ~[spring-beans-5.1.7.release.jar:5.1.7.release] at org.springframework.validation.databinder.convertifnecessary(databinder.java:693) ~[spring-context-5.1.7.release.jar:5.1.7.release] at org.springframework.web.method.annotation.abstractnamedvaluemethodargumentresolver.resolveargument(abstractnamedvaluemethodargumentresolver.java:124) ~[spring-web-5.1.7.release.jar:5.1.7.release] ... 81 more
failed to convert value of type 'java.lang.string' to required type 'com.**.enumexpensetype';
nested exception is org.springframework.core.convert.conversionfailedexception:
failed to convert from type [java.lang.string] to type [com.**.enumexpensetype] for value '1';
nested exception is java.lang.illegalargumentexception: no enum constant com.***.enumexpensetype.1
实际上它却报了个错。转换失败了。
查看报错信息,可以定位到是spring框架中stringtoenumconverterfactory中转换失败,具体代码如下:
private static class stringtoenum<t extends enum> implements converter<string, t> { private final class<t> enumtype; public stringtoenum(class<t> enumtype) { this.enumtype = enumtype; } @override public t convert(string source) { if (source.isempty()) { // it's an empty enum identifier: reset the enum value to null. return null; } return (t) enum.valueof(this.enumtype, source.trim()); } }
是enum.valueof这里报错,enum.valueof的后面的值并不是我们的value,而是name(这里的小欢喜)。
所以,我们不能使用这个spring提供converter,需要自定义一个:stringtoenumconverterfactory
public class stringtoenumconverterfactory implements converterfactory<string, baseenum> { private static final map<class, converter> convertermap = new hashmap<>(); @override public <t extends baseenum> converter<string, t> getconverter(class<t> targettype) { converter<string, t> converter = convertermap.get(targettype); if(converter == null) { converter = new stringtoenumconverter<>(targettype); convertermap.put(targettype, converter); } return converter; } class stringtoenumconverter<t extends baseenum> implements converter<string, t> { private map<string, t> enummap = new hashmap<>(); stringtoenumconverter(class<t> enumtype) { t[] enums = enumtype.getenumconstants(); for(t e : enums) { enummap.put(string.valueof(e.getvalue()), e); } } @override public t convert(string source) { t t = enummap.get(source); if (t == null) { // 异常可以稍后去捕获 throw new illegalargumentexception("no element matches " + source); } return t; } } }
然后再将这个工厂配置到项目中webmvcconfigurationsupport:
@override public void addformatters(formatterregistry registry) { registry.addconverterfactory(new stringtoenumconverterfactory()); }
意思就是string 转 baesenum都走这个converter。
至此这个坑就算解决了。
以上就是本次介绍的全部知识点内容,感谢大家对的支持。
下一篇: 百香果泡牛奶能喝吗,答案在这里
推荐阅读