Java中在catch块传递上下文参数的核心是利用异常链:通过带cause的构造器(如Throwable(String, Throwable))包装原始异常,注入订单号等业务上下文,并推荐使用含结构化字段的自定义异常类,配合SLF4J+MDC实现日志与异常双重上下文保障。
java中在catch块里传递上下文参数,核心是利用异常链(chained exceptions)——即通过构造新异常时传入原异常作为cause,并在新异常的构造过程中注入上下文信息(如id、操作名、业务参数等),而不是简单地打印日志或吞掉异常。
用带cause的构造器包装异常
最直接的方式是捕获原始异常后,创建一个语义更明确的新异常(比如自定义业务异常),并把原异常设为cause,同时把关键上下文作为消息或字段携带进去:
- 避免直接抛出原始异常(丢失上下文)或只抛新异常(丢失堆栈根源)
- 推荐使用 Throwable(String message, Throwable cause) 构造器
- 消息中可拼接业务标识,例如:"处理订单[ORD-2024-789]时解析JSON失败"
封装上下文到自定义异常类
比字符串拼接更健壮的方式,是定义一个支持上下文字段的异常类:
- 添加final字段如 orderId、userId、operation
- 构造时接收这些参数 + 原始异常,全部保存;重写 toString() 或提供 getContextInfo() 方法便于诊断
- 这样排查时既能看完整堆栈链,又能直接取到结构化上下文,不依赖日志解析
避免常见反模式
以下做法会削弱异常链的价值:
- 调用 e.printStackTrace() 后静默吞掉异常(cause丢失,上下文无处落脚)
- 新建异常时不传cause(new RuntimeException("失败")),导致原始根因不可追溯
- 在message里硬编码大量动态参数(易被截断、难结构化解析),不如存字段
配合日志做上下文透传
异常链本身不自动打印上下文,需日志框架配合:
立即学习“Java免费学习笔记(深入)”;
- 使用SLF4J时,可在log语句中显式输出上下文:log.error("订单处理异常,订单号={}", orderId, e)
- 搭配MDC(Mapped Diagnostic Context),把orderId等放入线程上下文,确保整个调用链日志自动携带
- 这样即使异常最终被顶层捕获打印,日志里也天然包含上下文,和异常对象里的字段形成双重保障


















