spring boot全局异常处理器需结合@exceptionhandler与slf4j,用@slf4j注解+log.error("msg", args..., e)记录带堆栈日志,e为关键参数;通过httpservletrequest获取uri、ip等上下文;按异常类型分层记录(业务异常warn、系统异常error);配合mdc与trace id实现日志串联。

Spring Boot 中全局异常处理器记录日志,核心是把 @ExceptionHandler 方法和 SLF4J(如 Logback)结合使用,在捕获异常的第一时间打日志,并确保关键信息不丢失。
用 @Slf4j + log.error 记录基础异常日志
在全局异常处理器类上加 @Slf4j 注解,调用 log.error(String, Object...) 打印带堆栈的错误日志。重点传入异常对象本身作为最后一个参数,这样完整堆栈才能输出:
-
推荐写法:
log.error("用户登录失败 | 用户名: {}, 异常: {}", username, e.getMessage(), e); - 第三个参数
e是关键——没有它,日志里只有消息,看不到堆栈轨迹 - 前两个占位符用于结构化上下文(如请求路径、用户ID、参数摘要),便于排查
补充请求上下文,提升定位效率
仅记录异常不够,还要知道“谁、在哪儿、干了什么”。通过方法参数注入 HttpServletRequest 获取必要信息:
- 用
request.getRequestURI()和request.getMethod()记录接口路径与方式 - 用
request.getRemoteAddr()或工具类(如IPUtil.getRealIp(request))获取真实客户端 IP - 可选:解析 JWT Token 或 Session 获取当前用户名,写入日志前缀或字段
区分异常类型,分层记录详细度
不同异常应有不同日志策略。比如业务异常(BusinessException)通常无需堆栈,而系统异常(NullPointerException)必须留全栈:
-
业务异常:
log.warn("订单创建失败 | 订单号: {}, 原因: {}", orderNo, e.getMessage()); -
系统/未预期异常:
log.error("服务端未知异常 | URI: {}, IP: {}", uri, ip, e); - 避免所有异常都用
error级别,否则日志噪音大,真正严重问题易被淹没
配合唯一请求 ID 实现日志串联
单条日志再全,也难关联一次完整请求链路。需在请求入口生成并透传 trace ID:
- 用
OncePerRequestFilter拦截请求,从 Header(如X-Request-ID)读取或自动生成 UUID 存入 MDC - Logback 配置中使用
%X{X-Request-ID}将该 ID 注入每行日志 - 异常处理器里无需额外操作,MDC 已自动携带,
log.error(...)输出的日志天然带 ID











