枚举和字典

162 阅读4分钟

开发中都会用到字典和枚举,字典更主要是用于类似于前端下拉,一般配置在数据库中,而枚举更多是用于后台代码的开发中。

如:

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);
    }
}

数据库中这么配置

image.png 可以按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;
}