完成通过反射注册错误码的逻辑

This commit is contained in:
白茶清欢 2025-06-02 20:51:52 +08:00
parent c2b65a6be8
commit d2f53bd163
4 changed files with 81 additions and 27 deletions

View File

@ -20,7 +20,7 @@ public class CustomException extends RuntimeException {
// 根据code与
public CustomException(String code, Object data) {
this.code = code;
this.message = HashMapCache.getHashMapCache().getCodeMessage(code); // 根据code初始化Message
this.message = HashMapCache.getInstance().getCodeMessage(code); // 根据code初始化Message
this.data = data;
}
public CustomException(String code, String message, Object data) {

View File

@ -5,14 +5,15 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
// 基于hashmap实现的内存缓存
// 因为就是服务启动时初始化一次, 无需考虑多线程并发安全问题
public class HashMapCache {
// 单例: 汉模式
// 单例: 饿汉模式
private static final HashMapCache hashMapCache = new HashMapCache();
private final Map<Object, String> cache = new HashMap<>();
//将构造器设置为private禁止通过new进行实例化
@ -20,19 +21,35 @@ public class HashMapCache {
}
// 此处实现的是自定义注解的解析逻辑, 将错误码全部加载到内存中
public void loadCustomException(ApplicationContext applicationContext) {
Map<String, Object> customExceptionAnnotationMap = applicationContext.getBeansWithAnnotation(CustomExceptionScanAnnotation.class);
for(Object bean : customExceptionAnnotationMap.values()){
public void loadCustomException(ApplicationContext applicationContext) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
Map<String, Object> customExceptionScanAnnotationMap = applicationContext.getBeansWithAnnotation(CustomExceptionScanAnnotation.class);
for(Object bean : customExceptionScanAnnotationMap.values()){
Class<?> extensionClz = ClassUtils.getUserClass(bean);
CustomExceptionScanAnnotation customExceptionAnnotation = AnnotationUtils.findAnnotation(extensionClz, CustomExceptionScanAnnotation.class);
assert customExceptionAnnotation != null;
String[] scanPackageList = customExceptionAnnotation.exceptionPackageList();
String[] scanExceptionClassList = customExceptionAnnotation.exceptionClassList();
System.out.println(Arrays.toString(scanExceptionClassList));
System.out.println(Arrays.toString(scanPackageList));
String[] exceptionClassList = customExceptionAnnotation.exceptionClassList();
List<String> classList = getAllClassList(scanPackageList, exceptionClassList);
for (String className: classList) {
Class<?> classInstance = Class.forName(className);
// 判断是否实现接口
if(!ICustomExceptionAnnotation.class.isAssignableFrom(classInstance)) {
// 未实现接口
continue;
}
// 实现了接口
// 反射获取类实例
ICustomExceptionAnnotation iCustomExceptionAnnotation = (ICustomExceptionAnnotation) (classInstance.getDeclaredConstructor().newInstance());
Map<String, String> codeTable = iCustomExceptionAnnotation.getCodeTable();
// TODO : 获取分类注解
for (Map.Entry<String, String> entry: codeTable.entrySet()) {
getInstance().put(entry.getKey(), entry.getValue());
}
}
}
}
public static HashMapCache getHashMapCache() {
// 获取实例
public static HashMapCache getInstance() {
return hashMapCache;
}
// 读取
@ -48,4 +65,55 @@ public class HashMapCache {
public void put(Object code, String message) {
cache.put(code, message);
}
// 获取一个包下的所有类列表
private List<String> getPackageClassList(String packageName) {
List<String> classList = new ArrayList<>();
String path = packageName.replace(".", "/");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
File directory = new File(Objects.requireNonNull(classLoader.getResource(path)).getFile());
if (!directory.exists()) {
return classList;
}
File[] fileList = directory.listFiles();
for (File file : fileList) {
String fileName = file.getName();
if (!fileName.endsWith(".class")) {
// 不是类文件
continue;
}
// 移除.class后缀
String className = packageName + "." + fileName.substring(0, fileName.length() - 6);
classList.add(className); // 添加到列表
}
return classList;
}
// 同时获取多个包下的class列表, 并支持重复的数据去重
private List<String> getClassListByPackageList(String[] packageList) {
List<String> classList = new ArrayList<>();
for (String packageName: packageList) {
List<String> packageClassList = getPackageClassList(packageName);
for (String className: packageClassList) {
if (classList.contains(className)) {
// 已存在, 无需重复添加
continue;
}
classList.add(className);
}
}
return classList;
}
// 获取输入的全部class列表
private List<String> getAllClassList(String[] packageList, String... configClassNameList) {
List<String> classList =getClassListByPackageList(packageList);
for (String className: configClassNameList) {
if (classList.contains(className)) {
// 已存在, 无需重复添加
continue;
}
classList.add(className);
}
return classList;
}
}

View File

@ -5,5 +5,5 @@ import java.util.Map;
// 为了支持注解扫描, 自定义exception必须实现此注解
public interface ICustomExceptionAnnotation {
// 获取错误码列表: code => message
public Map<Object, String> getCodeTable();
public Map<String, String> getCodeTable();
}

View File

@ -1,14 +0,0 @@
package cn.zhangdeman;
import org.junit.Assert;
import org.junit.Test;
import static org.junit.Assert.*;
public class HashMapCacheTest {
@Test
public void runHashMapCache() {
HashMapCache.getHashMapCache().put(200, "OK");
Assert.assertEquals("OK", HashMapCache.getHashMapCache().getCodeMessage(200));
}
}