文章目录

前言实现项目启动时加载枚举值到Redis1. 定义EnumInterface接口2. 创建EnumDTO3. 创建ClassUtils工具类4. 创建EnumService接口5. 创建EnumServiceImpl6. 修改枚举类7. 创建ApplicationInit

测试结果

前言

新的一年即将来到,回首2023年,也是学习了许多,不断进步。今天带来的是项目中遇到的一个业务要求处理方法总结:项目具有很多的枚举类,而这些枚举类在前端页面中需要作为下拉框选项等组件被前端获取。为了后续获取枚举值更加方便快捷,我们在项目启动的时候将所有Java枚举类用一个hash存入Redis中,在提供一个接口,使得前端可以从Redis获取自己想要的枚举值。下文将讲解实现步骤。

实现项目启动时加载枚举值到Redis

1. 定义EnumInterface接口

定义EnumInterface接口,实现该接口的枚举类会在后续被识别,在项目启动时加入redispublic 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反射获取某个包中所有的枚举类,将它们存入列表。 @Slf4j

public class ClassUtils {

//为了方便管理,我们将枚举类放在同一个包下,这里写入自己项目中枚举类所在的包名。

private static final String PACKAGE_NAME = "com.common.base.enums";

public static List> getAllEnumClasses() throws ClassNotFoundException, IOException {

List> 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) clazz);

}

}

return list;

}

/**

* 获取某包下的所有类

* @param packageName 包名

* @param childPackage 是否遍历子包

*/

public static List getClassName(String packageName, boolean childPackage) throws IOException {

List 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 getClassNameByFile(String filePath, boolean childPackage) throws UnsupportedEncodingException {

List 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

@Slf4j

public class EnumServiceImpl implements EnumService {

@Autowired

private RedisOperation redisOperation;

@Override

public void scanAndLoadEnumClassToRedis() {

try {

//声明Redis中存放的数据结构

Map> 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

String key = enumClass.getName() + "|" + enumInterface.enumDesc();

if (null == map.get(key)) {

List 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) ->

//存入Redis

redisOperation.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;

}

@Override

public String enumDesc() {

return "操作类型";

}

@Override

public 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

@Component

public class ApplicationInit implements ApplicationListener {

@Autowired

private EnumService enumService;

@Override

public void onApplicationEvent(ContextRefreshedEvent event) {

log.info("================开始初始化系统数据===========");

log.info("开始加载JAVA枚举值列表");

enumService.scanAndLoadEnumClassToRedis();

log.info("加载枚举值列表完成");

log.info("================初始化系统数据结束===========");

}

}

测试结果

上面的步骤完成后,就可以启动项目了,查看日志结果了: 日志成功打印之后,进入Redis可视化工具,可以看到Redis的枚举值已经存进去了,大功告成。

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: