模块间错误传递的关键是统一异常基类、边界处异常转换、保留异常链根因、接口契约显式声明错误语义。需继承basebusinessexception,含errorcode、httpstatus、traceid、timestamp字段;dao/rpc/service层须包装底层异常为语义明确的业务异常;每次包装必须传入cause,确保调用链完整可追溯。

模块间错误传递的关键是让异常携带可识别的语义、可追溯的上下文、可统一处理的结构,而不是把原始异常裸传或层层包装丢失关键信息。
统一异常基类,约束字段与行为
所有业务异常必须继承同一个顶层基类(如 BaseBusinessException),该类包含标准化字段:
-
errorCode:字符串类型业务码(如
"ORDER_NOT_FOUND"),不依赖 HTTP 状态码,前后端共用 -
httpStatus:整型状态码(如
404),供 Web 层直接映射响应 - traceId 和 requestId:从上游透传,确保跨模块链路可追踪
- timestamp:异常创建时间,对异步重试、定时任务排障有价值
模块边界处做异常转换,不裸传底层异常
每个模块对外暴露的异常应只体现本层语义,屏蔽内部技术细节:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- DAO 层遇到
SQLException,不直接抛出,而是包装为DataAccessException(Unchecked)或带明确业务含义的InventoryLockFailedException - RPC 客户端层捕获
FeignException或TimeoutException,转为RemoteCallException(Checked,仅当调用方需主动重试时)或ServiceUnavailableException(Unchecked) - Service 层不抛
NullPointerException或IllegalArgumentException,而用OrderAmountInvalidException这类命名精准的子类,并在构造时注入orderId、amount等关键字段
异常链必须保留根因,避免断链
每次包装异常都必须通过构造器传入 cause,确保堆栈中完整呈现“原始错误 → 中间转换 → 最终业务异常”的链条:
- 错误写法:
throw new OrderProcessException("下单失败")—— 根因丢失 - 正确写法:
throw new OrderProcessException("下单失败", e)—— JVM 自动记录 cause,日志打印时可展开全部层级 - 若需补充上下文,可用
Throwable.addSuppressed()添加辅助异常(如清理资源时发生的次级异常)
接口契约显式声明错误语义
模块提供的 API 必须通过 OpenAPI 或注解明确哪些错误可能被抛出:
- 使用
@ApiResponse在 Controller 方法上标注400(业务拒绝)、503(依赖不可用)等响应及其对应ErrorResponseSchema - 非 Web 模块(如 SDK、内部 lib)在 Javadoc 中说明方法可能抛出的异常类型及触发条件,例如:
/** @throws InventoryInsufficientException 当库存不足且无法锁定时抛出 */ - 避免在接口签名中声明泛化异常(如
throws Exception),每个公开方法只声明它真正会抛出的、有明确定义的子类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










