diff --git a/src/main/java/cn/zhangdeman/CustomException.java b/src/main/java/cn/zhangdeman/CustomException.java index 0031a9c..f034c64 100644 --- a/src/main/java/cn/zhangdeman/CustomException.java +++ b/src/main/java/cn/zhangdeman/CustomException.java @@ -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) { diff --git a/src/main/java/cn/zhangdeman/HashMapCache.java b/src/main/java/cn/zhangdeman/HashMapCache.java index 3b29382..3483636 100644 --- a/src/main/java/cn/zhangdeman/HashMapCache.java +++ b/src/main/java/cn/zhangdeman/HashMapCache.java @@ -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 cache = new HashMap<>(); //将构造器设置为private禁止通过new进行实例化 @@ -20,19 +21,35 @@ public class HashMapCache { } // 此处实现的是自定义注解的解析逻辑, 将错误码全部加载到内存中 - public void loadCustomException(ApplicationContext applicationContext) { - Map customExceptionAnnotationMap = applicationContext.getBeansWithAnnotation(CustomExceptionScanAnnotation.class); - for(Object bean : customExceptionAnnotationMap.values()){ + public void loadCustomException(ApplicationContext applicationContext) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { + Map 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 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 codeTable = iCustomExceptionAnnotation.getCodeTable(); + // TODO : 获取分类注解 + for (Map.Entry 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 getPackageClassList(String packageName) { + List 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 getClassListByPackageList(String[] packageList) { + List classList = new ArrayList<>(); + for (String packageName: packageList) { + List packageClassList = getPackageClassList(packageName); + for (String className: packageClassList) { + if (classList.contains(className)) { + // 已存在, 无需重复添加 + continue; + } + classList.add(className); + } + } + return classList; + } + + // 获取输入的全部class列表 + private List getAllClassList(String[] packageList, String... configClassNameList) { + List classList =getClassListByPackageList(packageList); + for (String className: configClassNameList) { + if (classList.contains(className)) { + // 已存在, 无需重复添加 + continue; + } + classList.add(className); + } + return classList; + } } diff --git a/src/main/java/cn/zhangdeman/ICustomExceptionAnnotation.java b/src/main/java/cn/zhangdeman/ICustomExceptionAnnotation.java index d8b1f95..da66e0f 100644 --- a/src/main/java/cn/zhangdeman/ICustomExceptionAnnotation.java +++ b/src/main/java/cn/zhangdeman/ICustomExceptionAnnotation.java @@ -5,5 +5,5 @@ import java.util.Map; // 为了支持注解扫描, 自定义exception必须实现此注解 public interface ICustomExceptionAnnotation { // 获取错误码列表: code => message - public Map getCodeTable(); + public Map getCodeTable(); } diff --git a/src/test/java/cn/zhangdeman/HashMapCacheTest.java b/src/test/java/cn/zhangdeman/HashMapCacheTest.java deleted file mode 100644 index 5b1f273..0000000 --- a/src/test/java/cn/zhangdeman/HashMapCacheTest.java +++ /dev/null @@ -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)); - } -} \ No newline at end of file