如何优雅的在Java应用中实现全局枚举处理

 

背景描述

为了表达某一个属性,具备一组可选的范围,我们一般会采用两种方式。枚举类和数据字典,两者具有各自的优点。枚举类写在Java代码中,方便编写相应的判断逻辑,代码可读性高,枚举类中的属性是可提前预估和确定的。数据字典,一般保存在数据库,不便于编写判断和分支逻辑,因为数据如果有所变动,那么对应的代码逻辑很有可能失效,强依赖数据库数据的正确性,数据字典中对应的属性对业务影响并不大,日常开发中常用做分类,打标签使用,属性的多少无法估计。

目前基本上没有一个很好的全局处理枚举类的方案,所以我就自己综合各方面资料写了一个。

代码

架构还在不断完善中,代码不一定可以跑起来,不过关于枚举的配置已经完成,大家可以阅读并参考借鉴:pretty-demo

前言

大多数公司处理枚举的时候,会自定义一个枚举转换工具类,或者在枚举类中编写一个静态方法实现Integer转换枚举的方式。比如:

// 静态方法方式 public enum GenderEnum {       // 代码略           public static GenderEnum get(int value) {          for (GenderEnum item : GenderEnum.values()) {             if (value == item.getValue()) {                  return item;              }          }          return null;      } } // 工具类方式 public class EnumUtil {      public static <E extends Enumerable> E of(@Nonnull Class<E> classType, int value) {         for (E enumConstant : classType.getEnumConstants()) {             if (value == enumConstant.getValue()) {                 return enumConstant;             }         }         return null;     }  }  GenderEnum gender = EnumUtil.of(GenderEnum.class,1);

这种方式很麻烦,或者需要手动编写对应的静态方法,或者需要手动调用工具类进行转换。

解决方案

为了方便起见,我做了一个全局枚举值转换的方案,这个方案可以实现前端通过传递int到服务端,服务端自动转换成枚举类,进行相应的业务判断之后,再以数字的形式存到数据库;我们在查数据的时候,又能将数据库的数字转换成java枚举类,在处理完对应的业务逻辑之后,将枚举和枚举类对应的展示信息一起传递到前台,前台不需要维护这个枚举类和展示信息的对应关系,同时展示信息支持国际化处理,具体的方案如下:

1、基于约定大于配置的原则,制定统一的枚举类的编写规则。大概规则如下:

  • 每个枚举类有两个字段: int value(存数据库),String key(通过key找对应的i18n文本信息)。这块需要细细讨论下,枚举值通常存数据库有存int值,也有存String值,各有利弊。存int的好处就是体积小,如果枚举的值是包含规律的,比如-1是删除,0是预处理,1是处理,2是处理完成,那么我们所有非删除数据,我们可以不使用 status in ( 0,1,2)这种方式,而转换为 status >= 0 ; 存String的话,好处就是可读性高,直接能从数据库的值中明白对应的状态,劣势就是占的体积大点。当然这些都是相对的,存int的时候,我们可以完善好注释,也具备好的可读性。如果int换成String,占的体积多的那一点,其实也可以忽略不计的。
  • 枚举枚举类需要继承统一接口,提供相应的方法供通用处理枚举时候使用。

下面是枚举接口和一个枚举示例:

public interface Enumerable<E extends Enumerable> {      /**      * 获取在i18n文件中对应的 key      * @return key      */     @Nonnull     String getKey();      /**      * 获取最终保存到数据库的值      * @return 值      */     @Nonnull     int getValue();      /**      * 获取 key 对应的文本信息      * @return 文本信息      */     @Nonnull     default String getText() {         return I18nMessageUtil.getMessage(this.getKey(), null);     } } public enum GenderEnum implements Enumerable {      /** 男 */     MALE(1, "male"),      /** 女 */     FEMALE(2, "female");      private int value;      private String key;      GenderEnum(int value, String key) {         this.value = value;         this.key = key;     }      @Override     public String getKey() {         return this.key;     }      @Override     public int getValue() {         return this.value;     } }

我们要做的就是,每个我们编写的枚举类,都需要按这样的方式进行编写,按照规范定义的枚举类方便下面统一编写。

2、我们分析下controller层面的数据进和出,从而处理好枚举类和int值的转换,在Spring MVC中,框架帮我们做了数据类型的转换,所以我们以 Spring MVC作为切入点。前台发送到服务端的请求,一般有参数在url中和body中两种方式为主,分别以get请求和post请求配合@RequestBody为代表。

【入参】get方法为代表,请求的MediaType为"application/x-www-form-urlencoded",此时将 int 转换成枚举,我们注册一个新的Converter,如果spring MVC判断到一个值要转换成我们定义的枚举类对象时,调用我们设定的这个转换器


                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信