小工具      在线工具  汉语词典  css  js  c++  java

枚举字典最佳实践

Java基础,java 额外说明

收录于:40天前

枚举是 Java 开发的重要组成部分。它们常用于定义单例工具类、常量、状态字典等。本文主要介绍使用枚举作为字典的最佳实践。

一、问题背景

一直做前后端分离开发的同学应该都遇到过这样的问题。比如有一个字段性别,包括男、女、未知。前端是下拉选择把男1、女2、未知3传过来,后端就保存了。数据库始终存储枚举值0,1,2。这种情况下,如果后端查询相关性别数据,只能找到0、1、2这样的数据,而无法返回对应的描述字段。如果前端也想要具体的描述字段怎么办?有两种选择

  1. 前端对字典表进行硬编码,后端循环将数据重新组装到前端。
  2. 提供前端字典接口,后端只传递code值,具体名称描述字段由前端转换

过去,该公司使用的是第一种解决方案。数据由后端提供,开发速度快,避免与前端打交道。但是,使用第一种方案有一个问题:如果我想加一个枚举,那前端和后端不都是一个字典表吗?一切都必须改变

其实我个人认为第二种方案更合理,但是作为单个项目,我不想创建与字典相关的表。我想直接用枚举类作为字典表返回给前端。那岂不是很美,所以我有以下想法:

将程序中需要提供给前端的枚举类存储到缓存中,并为前端提供字典查询接口,这样即使添加新的枚举,也只需要更改后端即可结尾。

二、最佳实践

1. 枚举抽象类

public interface BaseCodeEnum<T> {
    

    T getCode();

    String getName();

}
  • 限制枚举字段约束,为后续枚举工具类做准备
/** * @author: sunhhw * @date: 2023/12/8 12:25 * @description: 字典枚举值标记 */
public interface DictEnumAware<T> extends BaseCodeEnum<T> {
    

}
  • 感知结束标签,表示实现该接口的枚举需要以字典的形式返回给前端
public enum ArticleStatusEnum implements DictEnumAware<Integer> {
    

    PUBLISH(1, "发布"),
    DRAFTS(0, "草稿箱"),
    ;

    private final Integer code;
    private final String name;

    ArticleStatusEnum(Integer code, String name) {
    
        this.code = code;
        this.name = name;
    }

    @Override
    public Integer getCode() {
    
        return this.code;
    }

    @Override
    public String getName() {
    
        return this.name;
    }
}
  • 如果仅由程序内部使用,则只需实现 BaseCodeEnum 类即可。

2. 扫描枚举类

public enum EnumUtils {
    

    /** * 枚举标记 */
    X;

       /** * 根据枚举class获取该枚举的所有code,name列表 */
    public <T extends DictEnumAware<N>, N> DictEnumDTO getEnumList(Class<T> enumClass) {
    
        DictEnumDTO dictEnumDTO = new DictEnumDTO();
        List<DictDTO> dictDTOList = new ArrayList<>();
        for (T typeEnum : enumClass.getEnumConstants()) {
    
            DictDTO dictDTO = new DictDTO();
            N code = typeEnum.getCode();
            String name = typeEnum.getName();
            dictDTO.setCode(code.toString());
            dictDTO.setName(name);
            dictDTOList.add(dictDTO);
        }
        dictEnumDTO.setDictDTOList(dictDTOList);
        dictEnumDTO.setDictName(enumClass.getSimpleName());
        return dictEnumDTO;
    }


    public List<DictEnumDTO> registry(String basePackage) {
    
        List<DictEnumDTO> dictEnumDTOList = new ArrayList<>();
        try {
    
            PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
            MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(resourcePatternResolver);
            String packageSearchPath = "classpath*:" + basePackage.replace('.', '/') + "/**/*.class";
            Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);

            for (Resource resource : resources) {
    
                MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                if (classMetadata.isInterface() || classMetadata.isAbstract()) {
    
                    // 接口或抽象类,不处理
                    continue;
                }
                String[] interfaceNames = classMetadata.getInterfaceNames();
                for (String interfaceName : interfaceNames) {
    
                    if (interfaceName.equals(DictEnumAware.class.getName())) {
    
                        String className = classMetadata.getClassName();
                        Class<? extends DictEnumAware<Object>> clazz = (Class<? extends DictEnumAware<Object>>) Class.forName(className);
                        DictEnumDTO dictEnumDTO = getEnumList(clazz);
                        dictEnumDTOList.add(dictEnumDTO);
                        break;
                    }
                }
            }
        } catch (Exception e) {
    
            throw new ServiceException("字典类型初始化失败", e);
        }
        return dictEnumDTOList;
    }
}
  • 其中一些 DTO 类会自我补充
  • 使用PathMatchingResourcePatternResolverMetadataReaderFactory扫描指定包路径下的类,并筛选出该类是否实现DictEnumAware接口,找出对应的枚举类
  • 然后获取枚举类的code和name值并封装成DTO对象

3.存入缓存

@Test
public void test_01() {
    
    String packageName = "com.blog";
    List<DictEnumDTO> dictEnumDTOList = EnumUtils.X.registry(packageName);
    for (DictEnumDTO dictEnumDTO : dictEnumDTOList) {
    
        // 存入缓存
    }
}

4.提供接口

需要提供两个接口,一是根据枚举名称查询所有枚举列表,二是根据枚举名称和枚举码查询枚举名称。


我是1024,一个专注Java技术、记录生活的博主。

欢迎扫描二维码关注“1024公众号”,一起学习,一起进步,看更多路,少走弯路。

在这里插入图片描述

. . .

相关推荐

额外说明

python+chrome rpc方法轻松绕过五秒屏蔽(cloudflare)

 Cloudflare 5秒盾是一种基于云技术的Web应用程序防火墙(WAF),旨在保护网站免受各种Web攻击,如SQL注入、跨站点脚本(XSS)和DDoS攻击。它能够在5秒内检测到并阻止恶意流量,并提供实时安全警报和日志记录。此外,它还提供了一系列安全

额外说明

SpringCloud学习笔记-将微服务注册到Eureka注册中心

目录 1.在该Module的pom文件中引入eureka依赖 2.在该module的src/main/resources/application.yml配置文件 3.启动对应的微服务 4.查看微服务是否启动成功 假如我有一个微服务名字叫user-serv

额外说明

CouchBase 备份和恢复

备份的executedNew2可以还原到executedNew (它本身有数据也没事) cbbackup http://192.168.1.30:8091 E:\CouchBase_Backup -u admin -p 123456 -b execute

额外说明

Java 算法 - 查找由相同字母组成的单词。

数据集:http://www.puzzlers.org/pub/wordlists/unixdict.txt import java.net.*; import java.io.*; import java.util.*; public class

额外说明

JQuery操作文档之插入节点

JQuery中提供了八个方法用来在文档的不同位置插入节点,具体如下: 序号 方法 描述 示例 1 append() 向每个匹配元素的内部追加内容 ($(A).append(B):在A的后面追加B,也就是将A作为B的最后一个子节点) HTML:<p>Hel

额外说明

注解、原生Spring、SchemaBased三种方式实现AOP【附详细案例】

目录 一、注解配置AOP 1. 开启注解支持 2. 在类和方法加入注解 3. 测试 4.  为一个类下的所有方法统一配置切点 二、原生Spring实现AOP 1. 引入依赖 2. 编写SpringAOP通知类 3. 编写配置类bean2.xml 4  测

额外说明

设计中的手写识别(输入法)思路 -- 下篇

(本文系转载,原文地址:http://blog.csdn.net/prsniper/article/details/16953403) 1. dump.h [cpp] view plain copy #ifndef __SPIDER_DUMP_H_  

额外说明

sqli-labs笔记

目录 前言 用到的一些东西: 注入流程 第一关 第二关 第三关 第四关 第五关 第六关 前言 如果你是使用的phpstudy,请务必将sql的版本调到5.5以上,因为这样你的数据库内才会有information_schema数据库,方便进行实验测试。 另

额外说明

【Python 随练】编写 gotoxy() 与 clrscr() 函数

题目: 编写 gotoxy() 与 clrscr() 函数 简介: 在本篇博客中,我们将解决一个编程问题:编写 gotoxy() 与 clrscr() 函数。gotoxy() 函数用于在终端屏幕上移动光标到指定位置,而 clrscr() 函数用于清除终端

额外说明

手把手教你用js实现手机通讯录功能(附源码)

js实现手机通讯录 效果图 需求 需求一:锚点 通过#id配合a标签使用 css中scroll-behavior属性的使用 需求二+需求三 获取汉字拼音的首字母 方法1:使用插件,这里推荐pinyin-pro 方法2:使用unicode 去重数组中冗余的

ads via 小工具