构建稳健异常处理体系需分层识别、精准响应、可控恢复:按业务异常、运行时异常、系统级故障三类分别处理,禁用空catch,统一入口响应,强化可观测性。

构建稳健的异常处理体系,核心不是“捕获所有异常”,而是分层识别、精准响应、可控恢复。重点在于区分错误类型、明确处理边界、保留可追溯上下文。
按异常性质分层处理
系统中异常大致分三类:可预期业务异常(如余额不足)、不可预期运行时异常(如空指针、NPE)、系统级故障(如数据库连接超时、网络中断)。每类应走不同路径:
- 业务异常建议用自定义异常抛出,不打印堆栈,由统一拦截器转为用户友好的提示(如“当前账户余额不足,请充值”)
- 运行时异常需记录完整堆栈+关键业务参数(如订单ID、用户ID),并触发告警,但不暴露给前端
- 系统级故障要引入降级和重试机制,比如调用第三方接口失败时,先查本地缓存或返回兜底数据,避免雪崩
避免“吞掉”异常的陷阱
空catch块、只打印日志却不通知监控、或简单返回null而不说明原因,都是高危操作。真实项目中,这类写法常导致问题排查周期拉长数小时。
- 每个catch块必须至少做一件事:记录日志(含traceId)、上报指标、触发告警、或执行补偿逻辑
- 禁止在service层直接try-catch后return null;若无法处理,应向上抛出,交由更上层决定是重试、降级还是透传错误
- 日志中务必包含唯一追踪ID和关键业务字段,方便链路排查
统一异常入口与标准化响应
使用@ControllerAdvice + @ExceptionHandler集中管理全局异常,避免重复代码,也便于后续统一升级策略(如增加熔断开关、动态限流)。
- 定义标准响应体,包含code(业务码而非HTTP状态码)、message、timestamp、requestId,必要时附details字段用于调试
- 对4xx类异常(如参数校验失败)返回HTTP 400,5xx类(服务端错误)返回500,但code字段承载更细粒度语义(如“PAY_BALANCE_INSUFFICIENT”)
- 敏感信息(如数据库报错、文件路径)绝不出现在message中,可通过配置开关控制details是否返回
补充可观测性支撑
异常处理是否有效,不能只靠代码逻辑判断,要靠数据反馈。
- 将异常类型、发生模块、QPS、平均耗时等维度打点到监控系统(如Prometheus),设置突增阈值告警
- 关键流程(如支付、下单)添加“异常率”看板,长期跟踪TOP异常类型,驱动根因改进
- 定期抽检error日志中的traceId,反向验证链路埋点完整性与上下游日志关联准确性










