枚举治理
背景
1、多版本运行开发枚举容易导致冲突,服务无感知
2、业务中使用枚举实例处理逻辑,API入参/返参的枚举类型,需要手动转换
3、API文档(Swagger)枚举描述需要手动列举枚举值,枚举添加/修改描述无法及时更新
4、数据库中的枚举字段,查询出来后需要根据枚举处理,得先转化实例判断,冗余复杂
5、API返回枚举展示值需要手动设置,重复代码较多
6、API接受枚举类型参数的校验场景,冗余复杂
解决方案
1、系统启动检查枚举是否存在冲突
2、API入参/返参支持序列化枚举类型
3、Dao持久层框架(mybatis),出入参支持枚举类型
4、swagger文档定制枚举动态渲染
5、API返回枚举展示值需要手动设置,重复代码较多
6、基于Validation支持枚举类型校验
实现方案
系统启动检查枚举是否存在冲突
- 定义枚举注解,标识组件管理的枚举
- 实现BeanDefinitionRegistryPostProcessor,启动扫描所有枚举类
- 遍历枚举值,检测是否存在冲突
API入参/返参支持序列化枚举类型(系统统一使用fastjson)
Fastjson调研:
默认枚举序列化器:com.alibaba.fastjson.serializer.EnumSerializer
默认枚举反序列化器:com.alibaba.fastjson.parser.deserializer.EnumDeserializer自定义重写EnumSerializer、EnumDeserializer 序列化、反序列化器
覆盖fastjson FastJsonHttpMessageConverter默认配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@Component
public class FastJsonPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException{
if(bean instanceof FastJsonHttpMessageConverter){
FastJsonHttpMessageConverter messageConverter = (FastJsonHttpMessageConverter)bean;
FastJsonConfig fastJsonConfig = messageConverter.getFastJsonConfig();
fastJsonConfig.setParserConfig(new EnumParserConfig());
fastJsonConfig.setSerializeConfig(new EnumSerializeConfig());
}
return bean;
}
}
Dao持久层框架(mybatis)出入参支持枚举类型
- 自定义枚举类型转换器TypeHandler
- 注入所有枚举类型转换器到mybatis的SqlSessionFactory
Swagger文档定制枚举动态渲染
- 重写ModelPropertyBuilderPlugin自定义枚举,动态列举枚举实例描述
API返回枚举展示值自动渲染输出
举类型字段abc序列化时,在同级目录自动输出abcStr展示字段 如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36@EnumAnnotation
public enum ServerType {
/**
* 1 - ISC
*/
ISC(1,"ISC"),
/**
* 2 - 萤石
*/
YS(2,"萤石"),
;
@Getter
@EnumValue
private final Integer code;
@Getter
@EnumName
private final String name;
ServerType(Integer code, String name) {
this.code = code;
this.name = name;
}
public static class DefaultEnumMatcher implements EnumMatcher<VideoType>{
@Override
public boolean matches(VideoType targetEnum){
return Arrays.asList(VideoType.values()).contains(targetEnum);
}
}
}
在序列化出参时,转化为
{
"serverType":1,
"serverTypeStr":"ISC"
}
基于Validation支持枚举类型校验
- 自定义@EnumValid注解,用于标注需要校验的枚举字段
- 自定义ConstraintValidator,校验@EnumValid
- 定义枚举时,定义默认枚举校验器如上文:ServerType.DefaultEnumMatcher
解决痛点
- API入参支持使用枚举类型接受
- API入参枚举类型支持校验
- API出参自动渲染枚举展示名称
- 持久层出入参支持枚举类型
- API枚举入参支持swagger动态渲染
- 启动自动监测枚举冲突
缺点
1、修改了实体的序列化反序列化方式,不支持序列化后反序列化或者反序列化后序列化操作
2、依赖FastJson、Swagger3.0、Mybatis,版本兼容性较低、普适性较低
3、API出参序列化输出枚举展示字段,但是暂不支持在Swagger上输出该字段
后续优化
1、API出参序列化输出枚举展示字段,支持在Swagger上输出该字段