枚举
咩咩咩针对枚举类型,做了一系列扩展与适配。在开发过程中,针对枚举值我们通常会定义一个特定的枚举类型:
public enum Gender {
MALE,
FEMALE,
;
}
在开发中,只需要将获取到的数据库的string值,使用 Enum.valueOf(Gender.class, "MALE") 来将string值转换为枚举对象,或者通过 Gender.MALE.name() 方法将枚举转换为数据库所要的 string。
这种方式来处理枚举有以下几个优点:
- 使用jdk本身提供的功能即可,不需要做额外的扩展,且比较、转换都比较容易
- 同样的,在mybatis、jackson等框架中,本身也提供了对枚举的支持
- 枚举类相对更精简,存入的字符串可读性也比较高
同样的,也有一些缺点,这些缺点导致我们通常不在项目中使用纯枚举类:
- 存储的数值,通常可能不是枚举对象的名字,我无法自定义存储值
- 数据类型受限,我可能需要数字类型的枚举,与上述实际是一个问题
- jdk提供的
Enum.valueOf()方法,在找不到对应的枚举值时,会抛出异常,并且我很难对这个方法进行规则定义,比如如果传入null,就返回一个NULL的枚举值。
故在项目中我们会通常自定义一个拥有自己字段的枚举类型,并定义根据code获取枚举、获取message的工具方法:
@AllArgsConstructor
@Getter
public enum Gender {
MALE(0, "男人"),
FEMALE(1, "女人"),
;
private final Integer code;
private final String message;
public static Gender getEnums(Integer code) {
for (Gender type : Gender.values()) {
if (type.code.equals(code)) {
return type;
}
}
return null;
}
}
这种方式也很繁琐:
- 每次定义枚举,都要copy一份getEnum方法
- mybatis的实体,很难直接使用枚举类型,除非你对每个枚举进行注册
- jackson与mybatis的问题类似,不过jackson可以对code字段增加
@JsonValue字段来解决这个问题
因为这些痛点,miemiemie对枚举的处理就应运而生了。
CommonEnum
在 miemiemie-core 模块的 enums 包下,定义了一个 CommonEnum 接口,该接口是对所有枚举的抽象接口,他提供了一些方法,可以让我们方便的定义枚举、使用枚举:
// 拥有两个泛型,一个代表code字段的类型(枚举唯一标记)、一个代表message的类型
public interface CommonEnum<K, V> {
K getCode();
V getMessage();
}
如果要定义一个枚举,需要实现此接口,并添加code和message字段:
@AllArgsConstructor
@Getter
public enum Gender implements CommonEnum<Integer, String> {
MALE(0, "男人"),
FEMALE(1, "女人"),
;
private final Integer code;
private final String message;
}
如果想要根据枚举值获取对应的枚举,获取获取对应的描述信息,CommonEnum同样提供了一些静态方法,可以让你完成这些操作:
CommonEnum.getOptionalEnum(0, Gender.class);CommonEnum.getEnum(0, Gender.class);CommonEnum.getMessage(0, Gender.class);CommonEnum.getOptionalMessage(0, Gender.class);
CommonEnum的扩展
CommoneEnum提供了几个默认的实现:
NameCodeEnum,以枚举类的name()作为code的CommonEnumOrdinalCodeEnum,以枚举类的ordinal()作为code的CommonEnum
这两个都不建议使用。
对Jackson的支持
为了让枚举无缝的与Json序列化、以及web接口支持,在 miemiemie-web 的 jackson包下,定义了
CommonEnumDeserializer,在返序列化时将CommonEnum枚举code值转换为枚举对象CommonEnumSerializer, 在序列化时将CommonEnum枚举对象序列化,并且只序列化code值
这样,你就可以在请求体与响应体重,很方便的使用枚举类型,且不用在做烦人的字面量与枚举对象的转化了,并且枚举的判断也会更加简单。
备注: Jackson的配置位于
JacksonConfig,如果你对枚举的处理有扩展或者优化、或者不想使用该功能,可以对该bean进行修改,或者覆盖此Bean重新配置。
对MybatisPlus的支持
为了让entity可以无缝使用枚举类型,在miemiemie-mybatisplus模块的config包下,定义了两个类型处理器,可以自动将CommonEnum枚举类型处理为枚举类型的code值:
CommonEnumTypeHandler,核心处理CommonEnum的逻辑GenericEnumTypeHandler,通用枚举处理,包含了CommonEnum的逻辑,是为了兼容非实现了CommonEnum接口枚举而存在的
备注:在
MybatisPlusAutoConfig中配置了这这个类型处理器。
对OpenAPI的支持
你需要依赖miemiemie-openapi模块已实现openapi的功能,该模块相比较于spring提供的,多增加了对枚举字段类型的处理:
CommonEnumParameterCustomizerCommonEnumPropertyCustomizer
也就是说生成的API文档中,如果字段类型是CommonEnum枚举类型,则会在发送时,发送正常的枚举code值,而不是错误的枚举name()。并且在字段的展示上也更加人性化。
启动后访问地址 http://localhost:8080/swagger-ui/index.html:
