java异常日志应使用slf4j+logback,将throwable作为最后参数传入error/warn方法以保留完整堆栈,结合mdc注入traceid等上下文,避免空catch、重复记录或降级日志级别。

在 Java 中记录异常日志,核心是捕获异常后,用日志框架(如 Logback、Log4j2 或 SLF4J)输出带堆栈信息的可读日志,避免只打印 e.printStackTrace() 或空日志。
用 SLF4J + Logback 记录完整异常
SLF4J 是推荐的日志门面,Logback 是其原生实现。记录异常时,直接把 Throwable 对象作为最后一个参数传入日志方法,框架会自动打印完整堆栈:
-
✅ 正确写法(含堆栈):
logger.error("订单支付失败,用户ID: {}", userId, e); -
❌ 错误写法(丢失堆栈):
logger.error("订单支付失败,用户ID: {},异常: {}", userId, e.toString());
或logger.error("订单支付失败", e);(没占位符,消息体为空)
区分 log level,避免掩盖问题
根据异常性质选择合适的日志级别:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 业务异常(如余额不足、参数非法)→ 用
warn,不打断流程但需监控:logger.warn("充值金额超出限额,订单号: {}", orderId); - 系统异常(如数据库连接中断、NPE、IO 失败)→ 用
error,并传入异常对象:logger.error("查询用户详情失败,uid: {}", uid, e); - 调试阶段可临时用
debug记录受控异常,但上线前应移除或关闭 debug 日志
补充关键上下文,方便排查
单纯记录异常不够,要带上能定位问题的业务字段:
- 用户 ID、订单号、请求 ID(如 MDC 中的
traceId)、接口路径、时间戳等 - 推荐结合 MDC(Mapped Diagnostic Context)统一注入请求级上下文:
MDC.put("traceId", request.getTraceId());<br>MDC.put("userId", String.valueOf(userId));<br>logger.error("库存扣减失败", e);
Logback 配置中用%X{traceId} %X{userId}即可自动打印
不要吞掉异常或重复记录
常见反模式要避免:
- 空的
catch块:catch (Exception e) { /* 什么也不做 */ }→ 异常彻底丢失 - 多次记录同一异常(如 service 层 catch 并 log,controller 层又 try-catch 再 log)→ 日志爆炸且难溯源
- 用
info记录本该是 error 的异常(如网络超时)→ 告警规则可能漏掉 - 把异常转成字符串再拼接(
e.getMessage())→ 丢失 cause、stack trace 等关键信息
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










