java异常捕获时应结合日志框架结构化记录关键业务参数(如订单id、用户id)、脱敏敏感字段、利用mdc透传traceid,并按异常类型差异化输出上下文,避免仅打印堆栈或拼接字符串。

Java 异常捕获时结合日志框架记录关键参数,核心是在 catch 块中主动提取并结构化输出上下文信息,而不是只打堆栈。重点不是“要不要记日志”,而是“记哪些参数、怎么记才便于排查”。
捕获异常时显式记录业务关键参数
不要依赖 e.printStackTrace() 或仅记录 e.getMessage()。应在 catch 中把当前操作涉及的业务变量(如订单 ID、用户 ID、请求参数)一并写入日志。
- 用占位符方式拼接,避免字符串拼接影响性能(Logback/Log4j2 支持):
logger.error("订单支付失败,orderNo={}, userId={}, amount={}", orderNo, userId, amount, e); - 确保变量非 null,必要时做空判断或用
Objects.toString(x, "null")防 NPE - 敏感字段(如身份证、手机号)需脱敏后再记录,例如:
logger.info("用户登录,uid={}, phone={}", userId, DesensitizationUtils.mobile(phone));
利用 MDC 在日志中透传请求上下文
MDC(Mapped Diagnostic Context)可为单次请求绑定一组键值对,所有该线程后续日志自动携带,适合记录 traceId、requestId、sessionId 等。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在入口(如 Spring MVC 拦截器、Filter)中注入唯一 traceId:
MDC.put("traceId", UUID.randomUUID().toString().replace("-", "")); - 在 logback.xml 中配置 pattern,让 traceId 出现在每行日志开头:
%d{HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{36} - %msg%n - 务必在请求结束时调用
MDC.clear(),防止线程复用导致上下文污染
区分异常类型,按需记录不同参数
不同异常关注点不同:空指针要查哪个对象为 null,SQL 异常要看 SQL 和参数,远程调用异常需记 URL 和响应体。
-
NullPointerException:记录可疑对象引用和调用前的状态,例如:
logger.warn("用户信息为空,userId={},可能未登录或 token 失效", userId, e); -
SQLException:记录执行的 SQL(若已封装)、参数列表、错误码:
logger.error("DB 插入失败,sql={}, params={}, errorCode={}", sql, params, e.getSQLState(), e); -
FeignClient/RPC 异常:记录目标服务名、URL、超时时间、响应状态码(如有):
logger.error("调用用户服务超时,service=user-service, url={}, timeout={}ms", url, timeout, e);
避免日志泄露与性能陷阱
日志是排查利器,但滥用会引发安全风险或性能下降。
- 禁止记录原始 request body(含密码、token)、完整 response(含敏感数据),改用摘要或关键字段
- 避免在循环或高频方法中记录 ERROR 级别日志;可降级为 WARN,或加限流(如 Slf4j 的
logger.isErrorEnabled()+ 计数器) - 不要在日志中调用可能阻塞或抛异常的方法(如远程配置查询、复杂 toString()),保证日志语句本身绝对稳定
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










