gps/src/main/java/com/njzscloud/common/ex/ExceptionDepthComparator.java

94 lines
3.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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);
}
}