升级完善异常实现

This commit is contained in:
白茶清欢 2025-06-03 21:19:05 +08:00
parent e23e7969e1
commit 8d81df1ad6
6 changed files with 86 additions and 31 deletions

View File

@ -2,6 +2,8 @@ package cn.zhangdeman;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.util.Objects;
// 自定义异常 // 自定义异常
@Getter @Getter
@ -9,23 +11,37 @@ import lombok.Setter;
public class CustomException extends RuntimeException { public class CustomException extends RuntimeException {
private final String code; // 错误码 private final String code; // 错误码
private final String message; // 异常信息 private final String message; // 异常信息
private final String category; // 错误分类
private final Object data; // 异常数据 private final Object data; // 异常数据
public CustomException(String message) { public CustomException(String message) {
super(message); super(message);
this.code = "-1"; this.code = "-1";
this.category = "-1";
this.data = null; this.data = null;
this.message = message; this.message = message;
} }
// 根据code与 // 根据code与
public CustomException(String code, Object data) { public CustomException(ICustomExceptionConfig iCustomExceptionConfig, Object data) {
this.code = code; this.code = iCustomExceptionConfig.getCode();
this.message = HashMapCache.getInstance().getCodeMessage(code); // 根据code初始化Message this.message = iCustomExceptionConfig.getMessage();
this.category = iCustomExceptionConfig.getCategory();
this.data = data; this.data = data;
} }
public CustomException(String code, String message, Object data) { public CustomException(String category, String code, Object data) {
this.category = category;
this.code = code; this.code = code;
this.message = message; this.message = HashMapCache.getInstance().getCodeMessage(category, code);
this.data = data; this.data = data;
} }
// 是否制定分类的错误
public Boolean isCategory(String category) {
return this.category.equals(category);
}
// 是否指定分类下的指定错误
public Boolean isErrorCode(String category, String code) {
return this.category.equals(category) && this.code.equals(code);
}
} }

View File

@ -0,0 +1,27 @@
package cn.zhangdeman;
// 获取一个异常定义
public class CustomExceptionConfig implements ICustomExceptionConfig{
private final String category;
private final String code;
private final String message;
CustomExceptionConfig(String category, String code, String message) {
this.category = category;
this.code = code;
this.message = message;
}
@Override
public String getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
@Override
public String getCategory() {
return category;
}
}

View File

@ -6,6 +6,7 @@ import jakarta.servlet.ServletContextListener;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import java.io.File; import java.io.File;
@ -17,10 +18,11 @@ import java.util.*;
// 基于hashmap实现的内存缓存 // 基于hashmap实现的内存缓存
// 因为就是服务启动时初始化一次, 无需考虑多线程并发安全问题 // 因为就是服务启动时初始化一次, 无需考虑多线程并发安全问题
@Component
public class HashMapCache implements ServletContextListener { public class HashMapCache implements ServletContextListener {
// 单例: 饿汉模式 // 单例: 饿汉模式
private static final HashMapCache hashMapCache = new HashMapCache(); private static final HashMapCache hashMapCache = new HashMapCache();
private final Map<Object, String> cache = new HashMap<>(); private final Map<String, ICustomExceptionConfig> cache = new HashMap<>();
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
//将构造器设置为private禁止通过new进行实例化 //将构造器设置为private禁止通过new进行实例化
@ -39,33 +41,30 @@ public class HashMapCache implements ServletContextListener {
List<String> classList = getAllClassList(scanPackageList, exceptionClassList); List<String> classList = getAllClassList(scanPackageList, exceptionClassList);
for (String className: classList) { for (String className: classList) {
Class<?> classInstance = Class.forName(className); Class<?> classInstance = Class.forName(className);
// 判断是否实现接口 // 判断是否实现接口: 要求实现 ICustomExceptionAnnotation IExceptionConfig
if(!ICustomExceptionAnnotation.class.isAssignableFrom(classInstance)) { if(!ICustomExceptionAnnotation.class.isAssignableFrom(classInstance) || !ICustomExceptionConfig.class.isAssignableFrom(classInstance)) {
// 未实现接口 // 未实现接口
continue; continue;
} }
// 实现了接口 // 实现了接口
Map<String, String> codeTable = new HashMap<>();
// 反射获取类实例 // 反射获取类实例
if (!classInstance.isEnum()) { if (!classInstance.isEnum()) {
// 不是枚举类 // 不是枚举类
Constructor<?> constructor = classInstance.getDeclaredConstructor(); Constructor<?> constructor = classInstance.getDeclaredConstructor();
constructor.setAccessible(true);
ICustomExceptionAnnotation iCustomExceptionAnnotation = (ICustomExceptionAnnotation) (constructor.newInstance()); ICustomExceptionAnnotation iCustomExceptionAnnotation = (ICustomExceptionAnnotation) (constructor.newInstance());
codeTable = iCustomExceptionAnnotation.getCodeTable(); List<ICustomExceptionConfig> list = iCustomExceptionAnnotation.list();
for (ICustomExceptionConfig iCustomExceptionConfig: list) {
cache.put(iCustomExceptionConfig.getCategory()+"_"+iCustomExceptionConfig.getCode(), iCustomExceptionConfig);
}
} else { } else {
// 是枚举类 // 是枚举类
Method method = classInstance.getMethod("values"); Method method = classInstance.getMethod("values");
Object[] objectList = (Object[]) method.invoke(null); Object[] objectList = (Object[]) method.invoke(null);
for (Object itemEnumObject: objectList) { for (Object itemEnumObject: objectList) {
codeTable.put(((IExceptionConfig)itemEnumObject).getCode(), ((IExceptionConfig)itemEnumObject).getMessage()); ICustomExceptionConfig iCustomExceptionConfig = (ICustomExceptionConfig)itemEnumObject;
cache.put(iCustomExceptionConfig.getCategory()+"_"+iCustomExceptionConfig.getCode(), iCustomExceptionConfig);
} }
} }
// TODO : 获取分类注解
for (Map.Entry<String, String> entry: codeTable.entrySet()) {
getInstance().put(entry.getKey(), entry.getValue());
}
} }
} }
} }
@ -74,18 +73,28 @@ public class HashMapCache implements ServletContextListener {
return hashMapCache; return hashMapCache;
} }
// 读取 // 读取
public String getCodeMessage(Object code) { public String getCodeMessage(String category, String code) {
if (!cache.containsKey(code)) { String key = category + "_" + code;
if (!cache.containsKey(key)) {
// 不包含指定code // 不包含指定code
return code.toString(); return key;
} }
return cache.get(code); return cache.get(key).getMessage();
} }
// 添加 // 添加
public void put(Object code, String message) { public void put(String category, String code, String message) {
cache.put(code, message); String key = category + "_" + code;
cache.put(key, new CustomExceptionConfig(category, code, message));
} }
// 直接添加异常实例
public void putByConfig(ICustomExceptionConfig iCustomExceptionConfig) {
String key = iCustomExceptionConfig.getCategory() + "_" + iCustomExceptionConfig.getCode();
cache.put(key, iCustomExceptionConfig);
}
// 获取一个包下的所有类列表 // 获取一个包下的所有类列表
private List<String> getPackageClassList(String packageName) { private List<String> getPackageClassList(String packageName) {
List<String> classList = new ArrayList<>(); List<String> classList = new ArrayList<>();
@ -162,3 +171,4 @@ public class HashMapCache implements ServletContextListener {
public void contextDestroyed(ServletContextEvent sce) { public void contextDestroyed(ServletContextEvent sce) {
} }
} }

View File

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

View File

@ -0,0 +1,8 @@
package cn.zhangdeman;
// 异常的配置: 所属服务 + 错误分类 + 错误码全局唯一, 所属服务未配置, 将会随机生成
public interface ICustomExceptionConfig {
String getCode(); // 错误码
String getMessage(); // 错误信息
String getCategory(); // 错误分类
}

View File

@ -1,6 +0,0 @@
package cn.zhangdeman;
public interface IExceptionConfig {
String getCode();
String getMessage();
}