@restcontrolleradvice 必须配合 @exceptionhandler 方法才能捕获异常,仅加注解无效;需确保类被 spring 扫描,支持多方法按异常类型匹配,参数和返回值有严格限制,404/406 等非业务异常不进入该处理器。

@RestControllerAdvice 必须配合 @ExceptionHandler 才生效
单独加 @RestControllerAdvice 不会捕获任何异常,它只是个“容器”,真正干活的是里面定义的 @ExceptionHandler 方法。很多人加了注解但没写处理方法,结果 500 还是原样抛给浏览器。
- 必须确保类被 Spring 扫描到(加
@Component或放在主启动类同包下) - 一个
@RestControllerAdvice类里可以有多个@ExceptionHandler,按异常类型匹配,优先级由继承关系决定(子类异常优先于父类) - 如果多个
@ExceptionHandler都能匹配同一个异常(比如同时写了RuntimeException和NullPointerException),Spring 选最具体的那个
@ExceptionHandler 参数不能乱写,否则方法根本不会被调用
常见错误是往参数里塞 HttpServletRequest、HttpServletResponse 或自定义对象——这些不是 Spring 允许的参数类型,会导致该方法被跳过,降级到默认错误页。
- 合法参数包括:
Exception及其子类、WebRequest、HttpStatus、@RequestBody对应的 DTO(仅限请求体解析失败时)、@RequestHeader等绑定注解 - 返回值建议用
ResponseEntity>,方便统一设状态码和响应体;直接返回 POJO 也可以,但状态码默认是 200,得手动加@ResponseStatus - 别在
@ExceptionHandler里 throw 新异常,除非你确定上层还有人接——它自己不会二次兜底
404、406 这类非业务异常进不了 @ExceptionHandler
@ExceptionHandler 只处理控制器方法执行过程中抛出的异常,不处理 Spring MVC 自身的映射失败或内容协商失败。比如路径不存在(404)、Accept 头不支持(406)、JSON 解析失败(400)等,它们走的是另一套错误分发机制。
- 404 / 405 / 406 等由
BasicErrorController处理,默认返回 Whitelabel 页面;想接管就得自定义ErrorController或配置server.error.whitelabel.enabled=false+ 静态资源 - 请求体 JSON 解析失败(
HttpMessageNotReadableException)可以被捕获,但得显式声明:@ExceptionHandler(HttpMessageNotReadableException.class) - 全局日志记录建议用
@AfterThrowing切面,而不是全堆在@ExceptionHandler里,避免干扰响应逻辑
多个 @RestControllerAdvice 的执行顺序靠 @Order 控制
项目大了可能有多个全局异常处理器(比如基础模块一个、业务模块一个),不指定顺序时,Spring 按类名字母序加载,行为不可控。
- 必须用
@Order注解明确优先级,数值越小越先执行(@Order(1)比@Order(10)先) - 不要依赖默认顺序,哪怕只有一个
@RestControllerAdvice,也建议显式加@Order(1),避免未来引入新模块时冲突 -
@Order值重复时,Spring 会报错启动失败,这是好事——逼你理清职责边界
HttpMessageNotReadableException 和 MethodArgumentNotValidException 的覆盖,这两个一漏,前端传错 JSON 或校验失败就直接 400 响应体裸奔,连个 message 字段都没有。










