【Java】将枚举类转换为Redis字典缓存
时间:2022-11-24
本文章向大家介绍【Java】将枚举类转换为Redis字典缓存,主要内容包括字典翻译框架实现看这篇:、枚举的特性、使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
字典翻译框架实现看这篇:
https://www.cnblogs.com/mindzone/p/16890632.html
枚举的特性
首先是枚举的一些特性:
1、枚举实例直接在枚举类中声明
2、重载构造器,可以直观表示枚举的属性信息
3、枚举类的方法:
- values 可以获取枚举类的所有枚举项(数组)
- 枚举实例 ordinal() 方法获取枚举的下标值
- 枚举实例 name() 方法 获取你声明的实例名
4、枚举是完全单例的
5、枚举不可以作为通常对象响应给Web传数据,必须自己提取信息转换
package cn.hyite.amerp.common.state; import cn.hyite.amerp.common.state.intf.IEnumStateConvert; import lombok.Getter; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 盖印状态枚举类 * @author OnCloud9 * @version 1.0 * @project amerp-server * @date 2022年11月23日 13:31 */ @Getter public enum StampStateEnum implements IEnumStateConvert { UNUSED("未盖印", "0"), DONE("已盖印", "1"), CANCEL("已取消", "2"), ; public static final String CATE = "STAMP_STATE"; private final String code; private final String name; StampStateEnum(String name, String code) { this.name = name; this.code = code; } @SuppressWarnings("all") @Override public Map<String, String> getItem() { Map<String, String> instance = new ConcurrentHashMap<>(); instance.put("instName", name()); instance.put("instIndex", String.valueOf(ordinal())); instance.put("name", name); instance.put("code", code); return instance; } }
基于枚举,我们可以设置字典的属性,相比普通类更直观的表现【字典】
UNUSED("未盖印", "0"), DONE("已盖印", "1"), CANCEL("已取消", "2"),
我最初的设计几乎和DictDTO没区别,关键字段是 字典编号,字典名称,字典类别
存储方式就直接在应用中,不需要Redis,缓存的抽象设计沿用Redis的方案
package cn.cloud9.server.test.model; import lombok.AllArgsConstructor; import lombok.Getter; import org.apache.commons.collections.CollectionUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @author OnCloud9 * @description * @project tt-server * @date 2022年11月06日 下午 06:25 */ @Getter @AllArgsConstructor public enum MyType { GROUP1_TYPE1("a类型1", 1001, MyType.KEY_GP1), GROUP1_TYPE2("a类型2", 1002, MyType.KEY_GP1), GROUP1_TYPE3("a类型3", 1003, MyType.KEY_GP1), GROUP2_TYPE1("b类型1", 1001, MyType.KEY_GP2), GROUP2_TYPE2("b类型2", 1002, MyType.KEY_GP2), GROUP2_TYPE3("b类型3", 1003, MyType.KEY_GP2), GROUP3_TYPE1("c类型1", 1001, MyType.KEY_GP3), GROUP3_TYPE2("c类型2", 1002, MyType.KEY_GP3), GROUP3_TYPE3("c类型3", 1003, MyType.KEY_GP3), ; private final String name; private final Integer value; private final String cate; private static final Map<String, List<MyType>> typeList = new ConcurrentHashMap<>(); private static final Map<String, String> typeMap = new ConcurrentHashMap<>(); public static final String SEPARATOR = "@"; public static final String KEY_GP1 = "GT-1001"; public static final String KEY_GP2 = "GT-1002"; public static final String KEY_GP3 = "GT-1003"; static { for (MyType myType : MyType.values()) { final String myTypeCate = myType.getCate(); final String myTypeName = myType.getName(); final Integer myTypeValue = myType.getValue(); final String key = myTypeCate + SEPARATOR + myTypeValue; typeMap.put(key, myTypeName); List<MyType> myTypes = typeList.get(myTypeCate); if (CollectionUtils.isEmpty(myTypes)) { myTypes = new ArrayList<>(); typeList.put(myTypeCate, myTypes); } myTypes.add(myType); } } /** * 按枚举类别获取枚举集合 * @param cate * @return */ public static List<MyType> getTypeListByCate(String cate) { return typeList.get(cate); } /** * 按枚举类别获取枚举集合(响应用) * @param cate * @return */ public static List<Map<String, String>> getItemListByCate(String cate) { final List<MyType> myTypes = typeList.get(cate); if (CollectionUtils.isEmpty(myTypes)) return Collections.EMPTY_LIST; final ArrayList<Map<String, String>> items = new ArrayList<>(myTypes.size()); for (MyType myType : myTypes) { items.add(myType.getItem()); } return items; } /** * 按枚举类别和code获取名称 * @param cate * @param code * @return */ public static String getNameBy(String cate, Integer code) { String key = cate + SEPARATOR + code; return typeMap.get(key); } public Map<String, String> getItem() { Map<String, String> item = new ConcurrentHashMap<>(); item.put("instName", name()); item.put("instIndex", String.valueOf(this.ordinal())); item.put("name", this.name); item.put("value", String.valueOf(this.value)); return item; } }
但是老板认为一个枚举类不应该枚举所有的状态种类,一个枚举类就只负责一个特定状态类别:
例如:
1、审批状态
2、盖印状态
3、借还状态
翻译交给另外一个工具类来完成
加上我们已经习惯字典翻译框架的开发方式
在尽可能不动框架的情况下,就通过工具类来完成:
package cn.hyite.amerp.common.util; import cn.hyite.amerp.common.state.ApproveStateEnum; import cn.hyite.amerp.common.state.LendStateEnum; import cn.hyite.amerp.common.state.StampStateEnum; import cn.hyite.amerp.system.common.dict.dto.DictDTO; import org.apache.commons.collections.CollectionUtils; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; /** * 枚举缓存工具类,沿用Redis字典缓存方式初始化缓存 * @author OnCloud9 * @version 1.0 * @project amerp-server * @date 2022年11月24日 09:42 */ public class StateEnumUtil { private static final String DICT_CACHE_LISTS = "dict_cache_lists"; private static final String DICT_CACHE_KEYS = "dict_cache_keys"; private static final String SEPARATOR = "|"; private static final String DEFAULT_TABLE = "sys_co_dict"; private static final List<DictDTO> enumList = new ArrayList<>(); static { List<DictDTO> approveStateList = transToDictList(ApproveStateEnum.values(), ApproveStateEnum::getCode, ApproveStateEnum::getName, ApproveStateEnum.CATE); List<DictDTO> stampStateList = transToDictList(StampStateEnum.values(), StampStateEnum::getCode, StampStateEnum::getName, StampStateEnum.CATE); List<DictDTO> lendStateList = transToDictList(LendStateEnum.values(), LendStateEnum::getCode, LendStateEnum::getName, LendStateEnum.CATE); enumList.addAll(approveStateList); enumList.addAll(stampStateList); enumList.addAll(lendStateList); } public static void initialize() { /* 1、获取RedisTemplate */ StringRedisTemplate stringRedisTemplate = SpringContext.getBean(StringRedisTemplate.class); HashOperations<String, Object, Object> opsForHash = stringRedisTemplate.opsForHash(); /* 2、准备redis装载容器 */ Map<String, String> tmpMap = new HashMap<>(); Map<String, List<DictDTO>> tmpListMap = new HashMap<>(); /* 3、将枚举按字典的方式拼装 */ for (DictDTO dto : enumList) { String diCateIdent = dto.getDiCateIdent(); String diCode = dto.getDiCode(); /* hKey -> 字典表名 | 代码类别 | 代码编号 */ String key = DEFAULT_TABLE + SEPARATOR + diCateIdent + SEPARATOR + diCode; tmpMap.put(key.toUpperCase(), GsonUtil.toJson(dto)); /* hKey -> 字典表名 | 代码类别 */ String key2 = DEFAULT_TABLE + SEPARATOR + diCateIdent; List<DictDTO> list = tmpListMap.get(key2.toUpperCase()); if (CollectionUtils.isEmpty(list)) { list = new ArrayList<>(); tmpListMap.put(key2.toUpperCase(), list); } list.add(dto); } /* 4、推入Redis中,不做删除操作,共用缓存Key */ opsForHash.putAll(DICT_CACHE_KEYS, tmpMap); opsForHash.putAll(DICT_CACHE_LISTS, toJsonMap(tmpListMap)); LogUtil.COUNT_LOG.info("加载枚举缓存字典到Redis完毕..."); } private static Map<String, String> toJsonMap(Map<String, ?> tmpListMap) { Map<String, String> jsonList = new HashMap<>(tmpListMap.size()); for (Map.Entry<String, ?> entry : tmpListMap.entrySet()) { jsonList.put(entry.getKey(), GsonUtil.toJson(entry.getValue())); } return jsonList; } /** * 将枚举类集合转换为字典集合 * @param eArr 枚举类数组 * @param diCodeFunc 设置diCode取值方法 * @param diNameFunc 设置diName取值方法 * @param diCateIdent 设置diCateIdent值 * @return List<DictDTO> * @author OnCloud9 * @date 2022/11/24 10:40 */ private static <StateEnum extends Enum, FieldType> List<DictDTO> transToDictList(StateEnum[] eArr, Function<StateEnum, FieldType> diCodeFunc, Function<StateEnum, FieldType> diNameFunc, String diCateIdent) { List<DictDTO> dictList = new ArrayList<>(eArr.length); for (StateEnum e : eArr) { DictDTO dict = new DictDTO(); /* 1、设置字段编码 */ FieldType diCode = diCodeFunc.apply(e); dict.setDiCode(String.valueOf(diCode)); /* 2、设置字段名称 */ FieldType diName = diNameFunc.apply(e); dict.setDiName(String.valueOf(diName)); /* 3、设置字段类别 */ dict.setDiCateIdent(diCateIdent); /* 4、装载 */ dictList.add(dict); } return dictList; } }
在处理的钩子方法这里加上工具类的初始化:
package cn.hyite.amerp.common.cache; import cn.hyite.amerp.common.cache.impl.RedisCacheDictServiceImpl; import cn.hyite.amerp.common.cache.intf.CacheDictService; import cn.hyite.amerp.common.util.SpringContext; import cn.hyite.amerp.common.util.StateEnumUtil; /** * 业务数据缓存管理 * * @version 1.0 * @project portal-server * @author lianss * @date 2019年2月25日 下午6:19:36 */ public abstract class CacheManager { /** * 刷新缓存 * * @author lianss * @date :2019年2月25日 下午6:24:49 */ public static void refreshCache() { Thread refreshThread = new Thread(new RefreshCache()); refreshThread.start(); } } class RefreshCache extends Thread { @Override public void run() { CacheDictService cacheDictService = SpringContext.getBean(RedisCacheDictServiceImpl.class); cacheDictService.init(); StateEnumUtil.initialize(); } }
这里的难题主要是有各种各样的枚举类,需要有一个统一的方法来转换
提供枚举类,和字典属性的取值方法,可以生成字典集合
但是我不会写Lambda方法入参啊。。。,然后参考了一下MybatisPlus的lambdaQuery()源码,写出来了,
/** * 将枚举类集合转换为字典集合 * @param eArr 枚举类数组 * @param diCodeFunc 设置diCode取值方法 * @param diNameFunc 设置diName取值方法 * @param diCateIdent 设置diCateIdent值 * @return List<DictDTO> * @author OnCloud9 * @date 2022/11/24 10:40 */ private static <StateEnum extends Enum, FieldType> List<DictDTO> transToDictList(StateEnum[] eArr, Function<StateEnum, FieldType> diCodeFunc, Function<StateEnum, FieldType> diNameFunc, String diCateIdent) { List<DictDTO> dictList = new ArrayList<>(eArr.length); for (StateEnum e : eArr) { DictDTO dict = new DictDTO(); /* 1、设置字段编码 */ FieldType diCode = diCodeFunc.apply(e); dict.setDiCode(String.valueOf(diCode)); /* 2、设置字段名称 */ FieldType diName = diNameFunc.apply(e); dict.setDiName(String.valueOf(diName)); /* 3、设置字段类别 */ dict.setDiCateIdent(diCateIdent); /* 4、装载 */ dictList.add(dict); } return dictList; }
原文地址:https://www.cnblogs.com/mindzone/p/16922717.html
- 简单易学的机器学习算法——神经网络之BP神经网络
- 24(02)多线程锁,线程通讯,线程组,线程池,多线程三种方式,匿名内部类,定时器,设计模式,单例模式,Runtime
- Go代码打通HTTPs
- 一个简单的MySQL参数导致的连接问题解惑(r7笔记第33天)
- [基础篇]Go语言变量
- [转载]Golang 编译成 DLL 文件
- [转载]Go JSON 技巧
- 简单易学的机器学习算法——Rosenblatt感知机的对偶解法
- Spring-拾遗
- Golang面试题
- 简单易学的机器学习算法——基于密度的聚类算法DBSCAN
- 厚土Go学习笔记 | 29. 接口
- Golang Template 简明笔记
- hotspare的copyback(r7笔记第30天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【剑指Offer】包含min函数的栈
- 【剑指Offer】顺时针打印矩阵
- 从0打造属于自己的windows开发命令终端
- hadoop数据类型及自定义
- 惊!u202a错误,百分之九十都不知道的隐藏在文件路径里的惊天秘密!(干货收藏)
- 百度站点收录 - 什么叫自动推送
- 虚拟机安装Centos后的一些配置
- CentOS下的JDK安装
- python 技术篇-3行代码搞定图像文字识别,pytesseract库实现
- hadoop2.6.0完全分布式手动安装
- Python 库安装问题:ModuleNotFoundError: No module named 'windows'. 解决方法
- Python各种文件删除函数的功能区分!
- Python 技术篇-轻松操作windows系统电脑鼠标指针移动、点击
- Typora Picgo自动使用图床上传图片
- 【Python】文件的选择性压缩和全压缩,一般人不告诉的实用小技巧!