spring boot 枚举使用的坑整理

作者:二奎 时间:2022-09-17 09:03:15 

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.1at 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。

至此这个坑就算解决了。

来源:https://www.cnblogs.com/hankuikui/p/11429689.html

标签:spring,boot,枚举
0
投稿

猜你喜欢

  • Spring数据访问模板化方法

    2022-03-15 06:23:02
  • 一篇文章带你深入了解Java封装

    2023-11-20 00:37:45
  • Java框架解说之BIO NIO AIO不同IO模型演进之路

    2021-06-20 22:56:31
  • 百度人脸识别之人脸识别FaceIdentify(签到考勤)

    2022-08-24 18:25:03
  • Android判断设备网络连接状态及判断连接方式的方法

    2023-08-29 16:41:02
  • Android Dialog 设置字体大小的具体方法

    2023-09-12 12:46:49
  • C++ 前置声明详解及实例

    2023-02-28 10:39:46
  • Javaweb开发环境Myeclipse6.5 JDK1.6 Tomcat6.0 SVN1.8配置教程

    2023-11-15 21:47:05
  • C#快速实现IList非泛型类接口的自定义类作为数据源

    2022-10-09 20:28:24
  • Spring mvc拦截器实现原理解析

    2023-06-06 15:26:33
  • 浅谈Java线程间通信之wait/notify

    2022-06-09 11:26:19
  • java读取word-excel-ppt文件代码

    2022-07-06 14:20:46
  • Android创建和使用数据库SQLIte

    2023-04-03 17:18:01
  • Spring依赖注入与第三方Bean管理基础详解

    2022-09-08 20:45:55
  • Android编程基础之简单Button事件响应综合提示控件Toast应用示例

    2023-06-30 16:27:34
  • Android检测Activity或者Service是否运行的方法

    2021-09-03 00:52:00
  • java中BigDecimal和0比较的示例代码

    2022-07-05 04:58:18
  • Android开发中Button组件的使用

    2021-07-08 07:18:13
  • C#文件下载实例代码(适用于各个浏览器)

    2022-12-28 06:25:48
  • Android实现底部支付弹窗效果

    2022-06-12 13:39:43
  • asp之家 软件编程 m.aspxhome.com