Java--业务场景:在Spring项目启动时加载Java枚举类到Redis中

文章目录

        • 前言
        • 实现项目启动时加载枚举值到Redis
          • 1. 定义EnumInterface接口
          • 2. 创建EnumDTO
          • 3. 创建ClassUtils工具类
          • 4. 创建EnumService接口
          • 5. 创建EnumServiceImpl
          • 6. 修改枚举类
          • 7. 创建ApplicationInit
        • 测试结果

前言
  • 新的一年即将来到,回首2023年,也是学习了许多,不断进步。今天带来的是项目中遇到的一个业务要求处理方法总结:项目具有很多的枚举类,而这些枚举类在前端页面中需要作为下拉框选项等组件被前端获取。为了后续获取枚举值更加方便快捷,我们在项目启动的时候将所有Java枚举类用一个hash存入Redis中,在提供一个接口,使得前端可以从Redis获取自己想要的枚举值。下文将讲解实现步骤。
实现项目启动时加载枚举值到Redis
1. 定义EnumInterface接口
  • 定义EnumInterface接口,实现该接口的枚举类会在后续被识别,在项目启动时加入redis
    public interface EnumInterface {String getCode();String getDesc();//枚举类描述 该值后续会与枚举类名拼接 成为Redis hash的key  String enumDesc();}
    
2. 创建EnumDTO
  • 创建EnumDTO,将存放每个枚举类对象,同一个枚举类的所有对象最终会放入同一个列表,作为Redis hash的value。
      @Data@ApiModel(value = "EnumDto", description = "【枚举值-枚举值DTO】")public class EnumDto implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "枚举值类型-对应枚举值类名")private String typeEn;@ApiModelProperty(value = "枚举值类型-对应枚举值类名的desc描述信息")private String typeCh = "";@ApiModelProperty(value = "枚举值类型-对应枚举值的code值")private String code;@ApiModelProperty(value = "枚举值类型-对应枚举值的desc值")private String desc;@ApiModelProperty(value = "枚举值类型-对应枚举实例的名字")private String enumName;}
    
3. 创建ClassUtils工具类
  • 该类提供一个方法,通过Java反射获取某个包中所有的枚举类,将它们存入列表。
      @Slf4jpublic class ClassUtils {//为了方便管理,我们将枚举类放在同一个包下,这里写入自己项目中枚举类所在的包名。private static final String PACKAGE_NAME = "com.common.base.enums";public static List<Class<Enum>> getAllEnumClasses() throws ClassNotFoundException, IOException {List<Class<Enum>> list = new ArrayList<>();for (String className : getClassName(PACKAGE_NAME, true)) {Class<?> clazz = Class.forName(className);if (Enum.class.isAssignableFrom(clazz) && EnumInterface.class.isAssignableFrom(clazz)) {list.add((Class<Enum>) clazz);}}return list;}/*** 获取某包下的所有类* @param packageName  包名* @param childPackage 是否遍历子包*/public static List<String> getClassName(String packageName, boolean childPackage) throws IOException {List<String> fileNames = null;ClassLoader loader = Thread.currentThread().getContextClassLoader();String packagePath = packageName.replace(".", "/");URL url = loader.getResource(packagePath);if (url != null) {String type = url.getProtocol();if (type.equals("file")) {fileNames = getClassNameByFile(url.getPath(), childPackage);}} else {fileNames = getClassNameByJars(((URLClassLoader) loader).getURLs(), packagePath, childPackage);}return fileNames;}/*** 从项目文件获取某包下所有类**/private static List<String> getClassNameByFile(String filePath, boolean childPackage) throws UnsupportedEncodingException {List<String> myClassName = new ArrayList<>();// 解决路径包含中文的情况filePath = java.net.URLDecoder.decode(filePath,"utf-8");File file = new File(filePath);boolean exists = file.exists();File[] childFiles = file.listFiles();assert childFiles != null;for (File childFile : childFiles) {if (childFile.isDirectory()) {if (childPackage) {myClassName.addAll(getClassNameByFile(childFile.getPath(), childPackage));}} else {String childFilePath = childFile.getPath();if (childFilePath.endsWith(".class")) {childFilePath = childFilePath.substring(childFilePath.indexOf("\\classes") + 9,childFilePath.lastIndexOf("."));childFilePath = childFilePath.replace("\\", ".");myClassName.add(childFilePath);}}}return myClassName;}}
    
4. 创建EnumService接口
  • 创建EnumService接口,声明有关枚举类操作的接口
      public interface EnumService {/*** 扫描路径下的所有JAVA枚举类,并加载到redis缓存中*/void scanAndLoadEnumClassToRedis();}
    
5. 创建EnumServiceImpl
  • 创建EnumService实现类EnumServiceImpl,实现scanAndLoadEnumClassToRedis方法,该方法实现将枚举值加载到Redis中
      @Service@Slf4jpublic class EnumServiceImpl implements EnumService {   @Autowiredprivate RedisOperation redisOperation;@Overridepublic void scanAndLoadEnumClassToRedis() {try {//声明Redis中存放的数据结构Map<String, List<EnumDto>> map = new HashMap<>();//先删除原来的枚举类key,RedisKeyConstant.SYSTEM_ENUMS_CACHE_KEY 为存放缓存的key字符串,在常量类中自己定义redisOperation.del(RedisKeyConstant.SYSTEM_ENUMS_CACHE_KEY);//通过ClassUtils得到枚举类名,反射得到属性,填充属性到EnumDto中ClassUtils.getAllEnumClasses().forEach(enumClass -> {try {EnumInterface[] enumInterfaces = (EnumInterface[]) enumClass.getMethod("values").invoke(new Object());Arrays.stream(enumInterfaces).forEach(enumInterface -> {EnumDto enumDto = new EnumDto();enumDto.setCode(enumInterface.getCode());enumDto.setTypeEn(enumClass.getName());enumDto.setTypeCh(enumInterface.enumDesc());enumDto.setDesc(enumInterface.getDesc());enumDto.setEnumName(((Enum) enumInterface).name());//hash的key:枚举值类名|枚举类描述信息//hash的value:List<EnumDto>String key = enumClass.getName() + "|" + enumInterface.enumDesc();if (null == map.get(key)) {List<EnumDto> list = new ArrayList<>();list.add(enumDto);map.put(key, list);} else {map.get(key).add(enumDto);}});} catch (Exception e) {log.error("加载JAVA枚举值失败", e);redisOperation.del(RedisKeyConstant.SYSTEM_ENUMS_CACHE_KEY);throw new ProcessException(CommonConstants.ENUM_PROCESSING_EXCEPTION, "加载JAVA枚举值到Reids中发生错误,请检查代码!");}});map.forEach((key, val) -> //存入RedisredisOperation.hset(RedisKeyConstant.SYSTEM_ENUMS_CACHE_KEY, key, val));} catch (Exception e) {log.error("加载JAVA枚举值失败", e);throw new ProcessException(CommonConstants.ENUM_PROCESSING_EXCEPTION, "加载JAVA枚举值到Reids中发生错误,请检查代码!");}}}
    
6. 修改枚举类
  • 让需要加载到Redis中的枚举类实现EnumInterface接口,记得重写enumDesc方法,给枚举类们加上描述,这个描述很重要,以下是一个例子。
      public enum OperationTypeEnum implements EnumInterface {UPDATE("update", "更新"),DELETE("delete", "删除"),ADD("add","增加"),GET("show","展示");private final String code;private final String desc;OperationTypeEnum(String code, String desc) {this.code = code;this.desc = desc;}public String getCode() {return code;}@Overridepublic String enumDesc() {return "操作类型";}@Overridepublic String getDesc() {return this.desc;}public static String getDesc(String code) {for (OperationTypeEnum publishEnum : OperationTypeEnum.values()) {if (publishEnum.getCode().equals(code)) {return publishEnum.getDesc();}}return null;}public static OperationTypeEnum getByCode(String code) {for (OperationTypeEnum examSourceTypeEnum : OperationTypeEnum.values()) {if (examSourceTypeEnum.getCode().equals(code)) {return examSourceTypeEnum;}}return null;}}
    
7. 创建ApplicationInit
  • ContextRefreshedEvent是Spring内置的上下文更新事件,该事件会在ApplicationContext被初始化或者更新时发布。
      /*** 枚举值初始化* 系统启动的时候,将枚举值全部刷新一遍*/@Slf4j@Componentpublic class ApplicationInit implements ApplicationListener<ContextRefreshedEvent> {@Autowiredprivate EnumService enumService;@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {log.info("================开始初始化系统数据===========");log.info("开始加载JAVA枚举值列表");enumService.scanAndLoadEnumClassToRedis();log.info("加载枚举值列表完成");log.info("================初始化系统数据结束===========");}}
    
测试结果
  • 上面的步骤完成后,就可以启动项目了,查看日志结果了:
    在这里插入图片描述

  • 日志成功打印之后,进入Redis可视化工具,可以看到Redis的枚举值已经存进去了,大功告成。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/409771.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

❤ React报错问题分析

❤ React报错问题分析 ❤️ You passed a second argument to root.render(…) but it only accepts one argument. You passed a second argument to root.render(…) but it only accepts one argument. react-dom.development.js:86 Warning: You passed a second argumen…

Redis和MySQL如何保持数据一致性

前言 在高并发的场景下&#xff0c;大量的请求直接访问Mysql很容易造成性能问题。所以&#xff0c;我们都会用Redis来做数据的缓存&#xff0c;削减对数据库的请求。但是&#xff0c;Mysql和Redis是两种不同的数据库&#xff0c;如何保证不同数据库之间数据的一致性就非常关键…

科大讯飞星火大模型接入API js 部分 接口 安装注意事项

下载以下链接例子运行程序 https://xfyun-doc.xfyun.cn/static%2F16968175055332330%2Fspark_js_demo.zip 官网给的说明 准备 1.在demo中填写APPID、APISecret、APIKey&#xff0c;可到控制台-我的应用-大模型页面获取 2.安装nodejs 本地运行 1.打开cmd&#xff0c;进入dem…

CORS漏洞学习

CORS漏洞属于一个协议漏洞&#xff0c;具体是由于同源策略的设置问题触发的漏洞&#xff0c;漏洞利用条件较为苛刻&#xff0c;但实战中也常见。 首先要了解同源策略 什么是同源策略&#xff1f; 同源策略是一种Web浏览器安全机制&#xff0c;旨在防止网站相互攻击。 同源策…

网络安全的威胁PPT

建议的PPT免费模板网站&#xff1a;http://www.51pptmoban.com/ppt/ 此PPT模板下载地址&#xff1a;https://file.51pptmoban.com/d/file/2023/03/20/1ae84aa8a9b666d2103f19be20249b38.zip 内容截图&#xff1a;

刷题总结1.17 下午

第五题的平面图&#xff0c;偶图不理解 第三题为什么使用克鲁斯卡尔算法&#xff1f; 旅行商问题&#xff08;Traveling Salesman Problem&#xff0c;TSP&#xff09;是一个著名的组合优化问题&#xff0c;描述的是一个旅行商要在给定的一系列城市之间找到最短的路径&#xff…

MySQL下对[库]的操作

目录 创建数据库 创建一个数据库案例&#xff1a; 字符集和校验规则&#xff1a; 默认字符集&#xff1a; 默认校验规则&#xff1a; 查看数据库支持的字符集&#xff1a; 查看数据库支持的字符集校验规则&#xff1a; 校验规则对数据库的影响&#xff1a; 操作数据…

HCIA——10实验:跨路由转发。静态路由、负载均衡、缺省路由、手工汇总、环回接口。空接口与路由黑洞、浮动静态。

学习目标&#xff1a; 跨路由转发、负载均衡、环回接口、手工汇总、缺省路由、空接口与路由黑洞、浮动静态 学习内容&#xff1a; 跨路由转发静态路由、负载均衡、缺省路由、手工汇总。环回接口空接口与路由黑洞、浮动静态 目录 学习目标&#xff1a; 学习内容&#xff1a…

基于Springboot的摄影分享网站系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的摄影分享网站系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

linux基础学习(2):磁盘管理、分区、格式化

1.一些基本概念 一块磁盘从加入到可使用&#xff0c;需要经过3个阶段&#xff1a;分区-格式化-挂载。 1.1分区方式 linux有2种分区方式&#xff1a; &#xff08;1&#xff09;mbr&#xff1a;最大支持2.1T硬盘&#xff0c;最多支持4个分区。这4个分区可以全部为主分区&…

【java八股文】之计算机网络系列篇

1、TCP/IP和UDP模型 TCP/IP分层&#xff08;4层&#xff09;&#xff1a;应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层 网络的七层架构 &#xff08;7层&#xff09;&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff…

C++核心编程——文件操作

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; ---------第1阶段-C基础入门 ---------第2阶段实战…