关键在于构建“可预期、可追溯、可恢复”的错误响应机制:明确异常边界与职责分层、用try-with-resources保障资源安全、以事务或saga保证状态一致性、异常信息脱敏且带上下文。

在核心模块中落实异常安全编程,关键不是堆砌 try-catch,而是构建一套“可预期、可追溯、可恢复”的错误响应机制。它要求异常从产生到处理全程处于受控状态,不掩盖问题、不破坏状态、不泄露资源。
明确异常边界与职责分层
核心模块必须定义清晰的异常传播契约:
- 对外暴露的 API 方法只抛出业务语义明确的自定义异常(如 InsufficientBalanceException、InvalidOrderStateException),绝不抛出
RuntimeException或底层技术异常(如SQLException、HttpClientErrorException) - 数据访问层捕获技术异常后,统一转换为带错误码和上下文的业务异常,并保留原始异常作为 cause(启用异常链)
- 服务编排层不“吞掉”异常,而是根据场景决定:重试(幂等操作)、降级(返回兜底值)、熔断(触发限流策略)或向上透传
用 try-with-resources 替代手动 close
凡涉及文件、数据库连接、网络流、锁等资源,必须使用 try-with-resources。这是 Java 7+ 提供的语法保障,比 finally 块更可靠:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 资源声明在 try 括号内,JVM 确保无论是否异常都会调用
close() - 多个资源按声明逆序关闭,避免依赖冲突(如先关连接再关语句)
- 若 close() 抛异常,会被抑制(suppressed),可通过
e.getSuppressed()获取,不掩盖主异常
示例:错误写法是把 connection.close() 放进 finally;正确写法是 try (Connection conn = dataSource.getConnection()) { ... }。
状态一致性优先于异常捕获
核心模块常涉及多步状态变更(如扣库存 → 生成订单 → 发消息)。一旦中间失败,必须保证事务原子性或提供补偿能力:
- 数据库操作优先走本地事务(
@Transactional),避免手动 commit/rollback - 跨服务调用采用 Saga 模式:每个步骤附带对应的补偿动作(如“冻结库存”对应“解冻库存”)
- 避免在 catch 块中修改共享状态(如 set status = “FAILED”),应通过统一出口(如状态机 transition)驱动变更
异常信息要带上下文,但不带敏感数据
日志和监控中的异常堆栈必须能定位问题,又不能暴露用户隐私或系统密钥:
- 自定义异常构造时注入 traceId、bizId、操作人、关键参数(脱敏后),例如:
new OrderCreateException("库存不足", orderId, maskedUserId) - 记录日志时使用结构化日志框架(如 Logback + JSON encoder),字段分离,便于 ELK 过滤
- 禁止在异常消息中拼接原始 SQL、密码、token、完整请求体等
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










