欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring boot 枚举使用的坑整理

程序员文章站 2022-06-08 22:58:18
java 枚举的功能挺多,但是坑更多,使用的时候要注意。如下面这个枚举。 @getter @allargsconstructor public enum en...

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。

至此这个坑就算解决了。

以上就是本次介绍的全部知识点内容,感谢大家对的支持。