94 lines
3.0 KiB
Java
94 lines
3.0 KiB
Java
package com.njzscloud.common.ex;
|
||
|
||
|
||
import cn.hutool.core.lang.Assert;
|
||
import cn.hutool.core.lang.SimpleCache;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.Collection;
|
||
import java.util.Comparator;
|
||
import java.util.List;
|
||
|
||
/**
|
||
* <p>用于两个异常之间的排序</p>
|
||
* <p>根据当前异常与目标异常在异常继承体系中的层级进行比较</p>
|
||
*
|
||
* @see org.springframework.core.ExceptionDepthComparator
|
||
*/
|
||
public class ExceptionDepthComparator implements Comparator<Class<? extends Throwable>> {
|
||
|
||
/**
|
||
* 比较器缓存
|
||
*/
|
||
private static final SimpleCache<Class<? extends Throwable>, ExceptionDepthComparator> CACHE = new SimpleCache<>();
|
||
|
||
/**
|
||
* 目标异常类型
|
||
*/
|
||
private final Class<? extends Throwable> targetException;
|
||
|
||
/**
|
||
* 创建异常比较器
|
||
*
|
||
* @param exception 目标异常
|
||
*/
|
||
public ExceptionDepthComparator(Throwable exception) {
|
||
Assert.notNull(exception, "目标异常不能为空");
|
||
this.targetException = exception.getClass();
|
||
}
|
||
|
||
/**
|
||
* 创建异常比较器
|
||
*
|
||
* @param exceptionType 目标异常类型
|
||
*/
|
||
public ExceptionDepthComparator(Class<? extends Throwable> exceptionType) {
|
||
Assert.notNull(exceptionType, "目标异常类型不能为空");
|
||
this.targetException = exceptionType;
|
||
}
|
||
|
||
/**
|
||
* 从给定异常中获取最接近目标异常的匹配项
|
||
*
|
||
* @param exceptionTypes 待匹配的异常列表
|
||
* @param targetException 目标异常
|
||
* @return 匹配到的异常
|
||
*/
|
||
public static Class<? extends Throwable> findClosestMatch(Collection<Class<? extends Throwable>> exceptionTypes, Throwable targetException) {
|
||
Assert.notEmpty(exceptionTypes, "不能为空");
|
||
Assert.notNull(targetException, "不能为空");
|
||
if (exceptionTypes.size() == 1) {
|
||
return exceptionTypes.iterator().next();
|
||
}
|
||
List<Class<? extends Throwable>> handledExceptions = new ArrayList<>(exceptionTypes);
|
||
ExceptionDepthComparator comparator = CACHE.get(targetException.getClass(), () -> new ExceptionDepthComparator(targetException));
|
||
handledExceptions.sort(comparator);
|
||
return handledExceptions.get(0);
|
||
}
|
||
|
||
@Override
|
||
public int compare(Class<? extends Throwable> o1, Class<? extends Throwable> o2) {
|
||
int depth1 = getDepth(o1, this.targetException);
|
||
int depth2 = getDepth(o2, this.targetException);
|
||
return depth1 - depth2;
|
||
}
|
||
|
||
/**
|
||
* 获取异常的层级深度
|
||
*
|
||
* @param declaredException 待匹配的异常
|
||
* @param exceptionToMatch 目标异常
|
||
* @return 深度(≥0),越近数字越小
|
||
*/
|
||
private int getDepth(Class<?> declaredException, Class<?> exceptionToMatch) {
|
||
int depth = 0;
|
||
do {
|
||
if (exceptionToMatch.equals(declaredException)) return depth;
|
||
if (exceptionToMatch == Throwable.class) return Integer.MAX_VALUE;
|
||
depth++;
|
||
exceptionToMatch = exceptionToMatch.getSuperclass();
|
||
} while (true);
|
||
}
|
||
|
||
}
|