1. 错误处理概述:为什么需要全局错误处理
1.1 传统 try-catch 的痛点
在 Spring Boot 微服务架构中,错误处理不再是简单的“捕获异常→返回错误页面”。传统 try-catch 模式在单体应用时代尚可应付,但在分布式、高并发场景下暴露出以下核心问题:
| 痛点 | 具体表现 | 影响范围 |
|---|---|---|
| 代码侵入性强 | 每个 Controller 方法都需要重复编写 try-catch 块,业务逻辑与异常处理耦合 | 开发效率、可维护性 |
| 异常类型分散 | 不同层(DAO、Service、Controller)抛出不同类型的异常,调用方难以统一处理 | 接口一致性、客户端体验 |
| 响应格式不统一 | 有的返回 JSON、有的返回 HTML、有的直接抛 500 页面,前端无法统一解析 | 前后端协作、API 标准化 |
| 遗漏处理风险 | 开发人员容易忘记 catch 某些异常,导致未处理异常直接暴露给用户 | 系统稳定性、安全漏洞 |
| 日志与监控缺失 | 分散的 catch 块难以统一记录错误日志、采集监控指标 | 运维排障、SLA 保障 |
核心结论: 传统 try-catch 在微服务架构中已无法满足“统一、可观测、可治理”的错误处理需求,必须引入全局错误处理机制。
1.2 Spring Boot 错误处理机制演进
Spring Boot 从 1.x 到 3.x,错误处理机制经历了三次重要迭代,每一次都朝着“更集中、更灵活、更标准化”的方向演进:
- Spring Boot 1.x — BasicErrorController
默认提供/error映射,返回ModelAndView或Map,但定制能力有限,需继承重写。 - Spring Boot 2.x — @ControllerAdvice + @ExceptionHandler
引入全局异常处理器,支持按异常类型、按包路径、按注解粒度拦截,返回 JSON 或自定义视图。 - Spring Boot 3.x — ErrorAttributes + Problem Details (RFC 7807)
原生支持application/problem+json标准格式,与 Spring Cloud Gateway、Resilience4j 等熔断组件深度集成。
演进趋势: 从“视图导向”到“数据导向”再到“标准协议导向”。Spring Boot 3.x 的 Problem Details 机制为熔断降级链路提供了统一的错误契约。
1.3 为什么需要全局错误处理
在微服务链路中,一个请求可能经过网关、认证、业务 A、业务 B、数据库等多个节点。任何一个节点出错,如果没有全局兜底,错误会沿着调用链逐层传播,最终返回给客户端一个不可读的异常堆栈。全局错误处理的核心价值体现在四个维度:
- 统一响应契约 — 所有异常输出固定格式(code、message、timestamp、traceId),前端可统一解析。
- 链路可观测 — 全局处理器自动注入 traceId、spanId,与分布式链路追踪(如 Sleuth、Micrometer)打通。
- 熔断降级感知 — 当下游服务触发熔断(如 Resilience4j CircuitBreaker),全局处理器能识别
CallNotPermittedException并返回降级响应。 - 安全隔离 — 避免将数据库表名、SQL 语句、内部 IP 等敏感信息暴露给客户端。
常见误区: 全局错误处理 ≠ 吞掉所有异常。它只负责“统一格式 + 安全过滤 + 链路标记”,业务异常仍需在 Service 层显式抛出或处理。
1.4 全局错误处理的核心组件
一个完整的全局错误处理体系通常包含以下四个组件,它们共同构成“捕获→转换→记录→响应”的闭环:
| 组件 | 职责 | Spring Boot 实现方式 |
|---|---|---|
| 异常捕获器 | 拦截所有 Controller 层未处理异常 | @ControllerAdvice + @ExceptionHandler |
| 响应构建器 | 将异常转换为统一响应体(code、message、data) | 自定义 ErrorResponse 类或 ProblemDetail |
| 日志记录器 | 记录异常堆栈、请求参数、traceId 到日志系统 | MDC + SLF4J / Logback |
| 指标采集器 | 统计异常类型、频率、影响接口,上报监控系统 | Micrometer + Prometheus / Grafana |
实战要点: 在熔断降级链路中,异常捕获器需要额外识别
CircuitBreakerException、TimeLimiterException、BulkheadFullException 等 Resilience4j 异常,并映射到对应的降级响应码。