diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java index 82ea5caf1..16b352c3a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java @@ -14,6 +14,7 @@ import java.util.concurrent.*; @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Threads { + /** * 停止线程池 * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. @@ -60,4 +61,42 @@ public class Threads { log.error(t.getMessage(), t); } } + + /** + * 获取异常的根因(递归查找) + * + * @param e 当前异常 + * @return 根因异常(最底层的 cause) + *
+ * 逻辑说明:
+ * 1. 如果 e 没有 cause,说明 e 本身就是根因,直接返回
+ * 2. 如果 e 的 cause 和自身相同(防止循环引用),也返回 e
+ * 3. 否则递归调用,继续向下寻找最底层的 cause
+ */
+ public static Throwable getRootCause(Throwable e) {
+ Throwable cause = e.getCause();
+ if (cause == null || cause == e) {
+ return e;
+ }
+ return getRootCause(cause);
+ }
+
+ /**
+ * 在异常链中查找指定类型的异常
+ *
+ * @param e 当前异常
+ * @param clazz 目标异常类
+ * @return 找到的指定类型异常,如果没有找到返回 null
+ */
+ public static Throwable findCause(Throwable e, Class extends Throwable> clazz) {
+ Throwable t = e;
+ while (t != null && t != t.getCause()) {
+ if (clazz.isInstance(t)) {
+ return t;
+ }
+ t = t.getCause();
+ }
+ return null;
+ }
+
}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java
index d33f63f3b..7fa2bffaa 100644
--- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/MybatisExceptionHandler.java
@@ -1,10 +1,12 @@
package org.dromara.common.mybatis.handler;
+import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.http.HttpStatus;
+import com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
-import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.core.utils.Threads;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -35,17 +37,17 @@ public class MybatisExceptionHandler {
@ExceptionHandler(MyBatisSystemException.class)
public R