开发中都会用到字典和枚举,字典更主要是用于类似于前端下拉,一般配置在数据库中,而枚举更多是用于后台代码的开发中。
如:
1、是和否,字典定义一般0否1是,枚举中也要0否1是,在代码中如果是1执行某些逻辑
2、证件类型,1 身份证,2护照...,业务中可能存在如果是1或者2 则要校验证件号符不符合规则,比如用于从身份证里取出生日期
但是字典可以随便增删改,而枚举就不行了。所以对于这种字典,应该是一处定义多处使用,业务处理,不能随便修改,修改也要改代码,能做到修改一处枚举,多处判断逻辑同时更新。
在我的项目中遇到了这种问题,字典和枚举都配置并且数量还不少,需要把字典表里的字典去掉,改用枚举,把枚举返回前端作为字典使用。
字典类数据分为4种: 1、字典表中的数据; 2、枚举中的数据;3、版本区分字典(依赖产品或其它数据分区的);4、业务数据(医疗机构,医院,三目录等)
通用字典(1):返回1,2类字典,并且枚举中的数据会覆盖掉字典表中的数据
产品配置字典接口:返回依赖其它产品或数据区分的字典
我的想法
第一种:接口枚举,所有的枚举实现了同一个接口,我的想法是通过接口的实现类取到所有的枚举。后面想了一下对于现在的项目情况不适用。1)枚举太多,都要加接口工作量挺多还不一定能全部找到。2)枚举里有 code+name,type+name,code+label,type+desc,status+name ...,取不到具体的属性。
第二种:定义一个枚举,将枚举类和 前端的 code,label ,定义好,需要持续维护这些枚举。
第三种:针对不同的产品需求,可以配置枚举的值。如:有些情况下只有身份证,有些情况下需要身份证和护照。
我的实现:集合了4种情况 1、数据库字典,2、在枚举里分组,3、上面的第二种 ,用一个类维护,4、可以不同的配置
下面展示代码:
1、数据库就不说了,查询+代码
Collectors.groupingBy
2、
// 在这个枚举里配置好字典的类型和名称,字典内容是 class 类里、下一个属性方法的返回值
public enum ProductServiceDict {
REPORTING_OPTION("REPORTING_OPTION", "报案审核结果", ProductDictComponent.class, "getReportOption"),
FILING_OPTION("FILING_OPTION", "立案审核结果", ProductDictComponent.class, "getRegisterOption");
private final String dictType;
private final Class<?> implementClass;
private final String methodName;
public List<FrontDictDto> invoke(String param) {
try {
Method method = implementClass.getMethod(methodName, String.class);
Object bean = SpringUtil.getBean(implementClass);
return (List<FrontDictDto>) method.invoke(bean, param);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public List<FrontDictDto> getReportOption(String caseNode) {
List<AuditResultEnum> auditResultEnums = AuditResultEnum.getReportOption();
return auditResultEnums.stream().map(e -> new FrontDictDto(e.getTypeName(), e.getTypeCode())).collect(Collectors.toList());
}
public List<FrontDictDto> getRegisterOption(String caseNode) {
List<AuditResultEnum> auditResultEnums = AuditResultEnum.getRegisterOption();
return auditResultEnums.stream().map(e -> new FrontDictDto(e.getTypeName(), e.getTypeCode())).collect(Collectors.toList());
}
public static List<AuditResultEnum> getReportOption() {
return Stream.of(PASS, MATERIAL_QUESTION, CANCEL_CASE, INADMISSIBLE).collect(Collectors.toList());
}
public static List<AuditResultEnum> getRegisterOption() {
return Stream.of(PASS, REPORT_REVIEW_QUESTION, CANCEL_CASE, MATERIAL_QUESTION).collect(Collectors.toList());
}
获取代码配置的枚举字典
private Map<String, Object> getAllProductDict(String param) {
Map<String, Object> map = new HashMap<>();
ProductServiceDict[] byDictTypes = ProductServiceDict.values();
Stream.of(byDictTypes).forEach(e -> {
List<FrontDictDto> invoke = e.invoke(param);
map.put(e.name(), invoke);
});
return map;
}
3、扫描包的形式,启动时把包下的枚举放到缓存map 里
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Reflections reflection = new Reflections("com.winning.polaris.hmb.claimStandard.api.enums", Scanners.SubTypes);
Reflections reflections = new Reflections("com.winning.polaris.hmb.comm.enums", Scanners.SubTypes);
//理赔系统用枚举类,可按续获取
classInMap(reflection);
//系统全局用枚举类
classInMap(reflections);
}
private void classInMap(Reflections rt) {
//子类扫描器,抓取指定反射类中扫描到的类
Set<Class<? extends Enum>> allClasses = rt.getSubTypesOf(Enum.class);
for (Class<? extends Enum> clazz : allClasses) {
//获取枚举类下的所有枚举
Enum[] enumConstants = clazz.getEnumConstants();
Map<String, Enum> anyEnum = new HashMap<>();
for (Enum enumConstant : enumConstants) {
//把枚举的信息放入anyEum-map中
anyEnum.put(enumConstant.name(), enumConstant);
}
//cacheMap中放入每一个枚举类及其所有枚举信息
cacheMap.put(clazz.getSimpleName(), anyEnum);
}
}
数据库中这么配置
可以按policy_id查询出配置的数据,根据enum_name从cacheMap中取出枚举,再按照配置的dic_code过滤 cacheMap中的值,再用反射 取出枚举中 code 和 label的内容,还可以按照sort 排序。
public Map<String, List<FrontDictDto>> getNoPolicyData() {
Map<String, List<FrontDictDto>> map = new HashMap<>();
List<PolicyEnumConf> enums = mapper.queryEnums();
for (PolicyEnumConf anEnum : enums) {
List<FrontDictDto> frontDictDtos = new ArrayList<>();
Map<String, Enum> enumMap = cacheMap.get(anEnum.getEnumName());
if (enumMap == null) {
continue;
}
enumMap.values().forEach(e -> {
Object code = ReflectUtil.getFieldValue(e, anEnum.getFrontCode());
Object name = ReflectUtil.getFieldValue(e, anEnum.getFrontLabel());
FrontDictDto frontDictDto = new FrontDictDto(String.valueOf(name), String.valueOf(code));
frontDictDtos.add(frontDictDto);
});
map.put(anEnum.getDicType(), frontDictDtos);
}
return map;
}