Java全局异常处理需用logger.error("msg", throwable)自动记录堆栈,Spring Web用@ControllerAdvice+@ExceptionHandler,非Web场景设Thread.setDefaultUncaughtExceptionHandler,日志配置须含%ex/%throwable,禁用单参数log.error,推荐结合MDC记录请求上下文。

在 Java 中,全局异常处理自动记录堆栈轨迹到日志系统,核心是统一捕获未处理异常,并通过日志框架(如 Logback、Log4j2)的 logger.error(String, Throwable) 方法直接传入异常对象——这样日志框架会自动打印完整堆栈,无需手动调用 e.printStackTrace() 或拼接字符串。
使用 @ControllerAdvice + @ExceptionHandler(Spring Web 场景)
适用于 Spring MVC 或 Spring Boot Web 应用,拦截控制器层抛出的异常:
- 定义一个带
@ControllerAdvice的类,它会作用于所有@Controller和@RestController - 用
@ExceptionHandler(Exception.class)捕获通用异常(或指定更具体的类型,如RuntimeException) - 在方法体内调用
log.error("请求处理失败", e),第二个参数传异常对象即可输出完整堆栈
示例:
@ControllerAdvice
public class GlobalExceptionHandler {
<pre class="brush:php;toolbar:false;">private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(HttpServletRequest req, Exception e) {
String uri = req.getRequestURI();
log.error("接口 {} 发生未预期异常", uri, e); // ✅ 堆栈自动记录
return ResponseEntity.status(500).body("服务器内部错误");
}}
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
配置 Thread.setDefaultUncaughtExceptionHandler(非 Web 或异步线程)
Spring 的 @ControllerAdvice 无法捕获以下场景的异常:
- 定时任务(
@Scheduled)中抛出的未捕获异常 - 手动创建的线程(
new Thread(...).start()) - CompletableFuture 异步回调中的异常(未显式
exceptionally处理)
此时需设置 JVM 级别的默认未捕获异常处理器:
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
log.error("线程 [{}] 意外终止,异常:", thread.getName(), throwable);
});建议在 Spring Boot 启动类或 @PostConstruct 方法中初始化该处理器,并确保日志对象是线程安全的(SLF4J + Logback 默认支持)。
确保日志框架正确配置(关键细节)
即使代码传了异常对象,若日志配置不当,仍可能只打印消息、不显示堆栈:
- 检查日志输出格式是否包含
%ex(Logback)或%throwable(Log4j2)占位符。例如 Logback 的logback-spring.xml中:
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%ex</pattern>- 避免使用
log.error(e.getMessage())或log.error("xxx" + e)—— 这会丢失堆栈,甚至触发toString()导致信息不全 - 推荐始终使用双参数形式:
log.error("描述性消息", exception)
补充:记录请求上下文(增强可排查性)
单纯堆栈不够,建议在全局异常处理中一并记录关键上下文:
- 当前请求 URL、HTTP 方法、用户 ID(若有)、TraceID(集成 Sleuth/Zipkin 时)
- 可借助 MDC(Mapped Diagnostic Context)临时绑定上下文,例如在拦截器中放入 traceId,在异常处理器中自动写入日志行
- 对异步线程,注意 MDC 不会自动继承,需手动
MDC.copyToChildThread()或使用LogUtil.wrap()类似工具

















