spring boot全局异常处理是结构化、分层的统一机制:定义统一响应格式(code/message/data),分层抛异常(业务/参数/系统异常),用@restcontrolleradvice集中捕获并分级处理,配合拦截器与参数校验形成闭环。

Spring Boot 全局异常综合实战,核心是把“散落各处的 try-catch”收拢成一套可维护、可扩展、前后端友好的统一机制。它不是加一个注解就完事,而是一套有结构、有分工、有边界的设计实践。
定义统一响应格式(前端能直接用)
所有接口——无论成功、业务失败还是系统出错——都返回同一结构。比如:
- code:状态码(200 成功,400 参数错,401 未登录,403 无权限,500 系统异常)
- message:用户/运维可读的提示,不暴露堆栈或数据库细节
- data:业务数据(成功时有,失败时为 null)
用 Lombok + 静态工厂方法封装,例如 Result.success() 和 Result.error(400, "手机号格式错误"),避免每个接口手动 new 对象。
分层抛异常(业务逻辑不兜底)
异常要“说得清、分得明”,不能全扔 RuntimeException。推荐三类明确分工:
- 自定义业务异常(如 BusinessException):带 code 和 message,用于“用户不存在”“库存不足”等可预期场景,Service 层主动 throw
- 参数校验异常:用 @Valid + @NotBlank/@Email 等注解触发,框架自动抛 MethodArgumentNotValidException
- 系统级异常(如 NullPointerException、SQLException):不主动 throw,由框架或底层抛出,交给全局兜底
这样 Controller 层只写纯业务代码,不写 if 判空、不写 try-catch,异常自然向上冒泡。
用 @RestControllerAdvice 统一捕获(一个类管所有)
建一个类,加上 @RestControllerAdvice 注解,里面按优先级顺序写多个 @ExceptionHandler 方法:
- 先处理 BusinessException:取它的 code 和 message,包装成 Result 返回
- 再处理 MethodArgumentNotValidException:提取 BindingResult 中第一个错误字段和提示,组装成 “用户名不能为空” 这类友好信息
- 最后兜底 Exception:统一返回 500,记录完整日志(含请求路径、参数、堆栈),但响应体里只给 “系统繁忙,请稍后再试”
注意:不要在处理器里再 throw 新异常,也不要吃掉日志——ERROR 级必须记录原始异常,否则排查无从下手。
配合拦截器与参数校验形成闭环
全局异常不是孤立模块,它和登录校验、参数验证天然串联:
- 拦截器(Interceptor)先拦住未登录请求,直接返回 401,不进 Controller → 不触发异常处理器
- Controller 方法参数加 @Valid 后,校验失败会抛异常 → 被 @ExceptionHandler 捕获 → 返回 400 格式
- 业务中 throw BusinessException → 被捕获 → 返回对应 code(如 403)
- 其他任何未捕获异常 → 最终落到 Exception 的兜底方法 → 返回 500
整条链路清晰可控,每个环节只做一件事,改提示、调码值、加日志,都在一个地方完成。











