当前位置: 移动技术网 > IT编程>开发语言>Java > spring boot 枚举使用的坑整理

spring boot 枚举使用的坑整理

2019年09月06日  | 移动技术网IT编程  | 我要评论

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。

至此这个坑就算解决了。

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网