spring mvc中用@controlleradvice配合@exceptionhandler实现全局异常处理,核心是按异常类型精准拦截并返回统一result结构,配合@responsestatus或responseentity设置合理http状态码,避免捕获throwable。

Spring MVC 中用 @ControllerAdvice 配合 @ExceptionHandler 实现全局异常处理,核心是把原本散落在各 Controller 中的 try-catch 逻辑统一收口,让异常响应更规范、可维护性更强。关键不在于“捕获所有异常”,而在于“按类型精准拦截 + 返回一致格式”。
定义统一的异常响应结构
先设计一个前端友好的返回体,比如包含状态码、提示信息和可选数据:
public class Result<t> {
private int code;
private String msg;
private T data;
// 构造方法、getter/setter 省略
}</t>
这样后续所有异常处理器都返回 Result,避免前端反复适配不同结构。
用 @ControllerAdvice 声明全局异常处理器类
@ControllerAdvice 是一个增强型切面,它会自动作用于所有 @Controller(包括 @RestController)。建议加上 basePackages 明确作用范围:
- 加
@ResponseBody确保返回 JSON(Spring Boot 默认已生效,但显式写上更清晰) - 加
@Order(Ordered.HIGHEST_PRECEDENCE)可控制多个 Advice 的执行优先级 - 类名建议体现用途,如
GlobalExceptionHandler
用 @ExceptionHandler 按异常类型分别处理
每个 @ExceptionHandler 方法绑定一种或多种异常,Spring 会按匹配优先级(子类优先)调用最具体的那个:
- 处理业务异常(如自定义的
BusinessException):返回 200 + 业务错误码和提示 - 处理参数校验失败(
MethodArgumentNotValidException):提取BindingResult中的错误字段和消息 - 处理空指针等运行时异常(
RuntimeException):记录日志并返回通用错误(如 500) - 兜底处理
Exception:作为最后防线,避免未被捕获的异常穿透到容器
注意:不要直接捕获 Throwable,会吞掉系统级错误(如 OutOfMemoryError),不利于排查。
配合 @ResponseStatus 或 ResponseEntity 控制 HTTP 状态码
仅靠 @ExceptionHandler 不会自动改 HTTP 状态码,需显式指定:
- 用
@ResponseStatus(HttpStatus.BAD_REQUEST)注解方法,适合固定状态码场景 - 用
ResponseEntity<result></result>返回,可在方法内动态设状态码(例如根据异常内容返回 401 或 403) - 避免在所有异常里都返回 200,该是 4xx/5xx 就该是,利于前端判断和网关识别
示例片段:
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.OK) // 业务异常走 200
public Result<void> handleBusinessException(BusinessException e) {
return Result.fail(e.getCode(), e.getMessage());
}</void>
真正起效的关键不是堆砌注解,而是理清异常分类、明确每类的语义和响应契约。只要接口返回结构统一、状态码合理、日志可追溯,全局异常处理就落地了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











