全局异常处理器需记录完整异常对象而非仅消息,避免包装再抛出丢失根源,业务异常WARN级记录、系统异常ERROR级附上下文,防止静默吞掉异常。

全局异常处理器确实能统一响应、屏蔽堆栈,但若处理不当,很容易把原始异常“吃掉”——比如只记录了 e.getMessage(),却丢掉了关键的堆栈、根源异常(cause)、甚至嵌套异常链(getCause()、getSuppressed()),导致线上问题排查困难。
保留原始异常堆栈和上下文
在 @ExceptionHandler 方法中,必须用 log.error("msg", e) 的形式记录完整异常对象,而不是 log.error("msg: " + e.getMessage())。后者只打日志字符串,丢失堆栈和 cause 链。Spring Boot 默认日志框架(如 Logback)会自动展开整个异常链,包括 nested exceptions 和 suppressed exceptions。
不包装再抛出时丢失根源
避免在全局处理器里 new 一个新异常再 throw,例如:
✘ 错误写法throw new RuntimeException("系统繁忙", e); // 包装后原始类型丢失,堆栈被截断
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
如果必须转发异常(比如做降级或重试),应使用原始异常本身,或至少保留其 getCause() 和 getStackTrace();更推荐直接记录并返回友好响应,不再抛出。
区分业务异常与系统异常的处理粒度
自定义业务异常(如 BusinessException)通常无需打印完整堆栈(WARN 级即可),但系统级异常(NullPointerException、SQLException、Exception)必须用 ERROR 级 + 完整异常对象记录,并附带请求路径、参数、用户 ID 等上下文信息。
- 建议在日志模板中固定包含:
requestURI={}、params={}、userId={} - 使用 MDC(Mapped Diagnostic Context)注入请求唯一 traceId,便于全链路追踪
检查异常是否被静默吞掉
以下情况极易导致异常“消失”:
- 在
@ExceptionHandler方法里 catch 了异常,但没调用log.error(..., e),只写了log.warn(...)或什么都没记 - 异常被
try-catch在 Service 层捕获后未 re-throw,也未记录,最终全局处理器根本收不到 - 异步方法(
@Async)抛出的异常未配置AsyncUncaughtExceptionHandler,会直接丢失

















