最常用方式是@controlleradvice+@exceptionhandler组合,用于全局捕获controller异常并返回统一响应;拦截器无法真正处理异常,仅适合日志监控等事后通知。

在 Spring 中,异常处理最常用的方式是结合 @ControllerAdvice 和 @ExceptionHandler 实现全局统一响应格式,而不是用“拦截器”(Interceptor)来处理异常——因为拦截器作用于请求进入 Controller 之前或之后,无法捕获 Controller 中抛出的异常。真正负责异常统一处理的是 Spring 的异常解析机制,核心是 HandlerExceptionResolver,而 @ControllerAdvice 是其最简洁高效的使用方式。
用 @ControllerAdvice + @ExceptionHandler 统一返回结构
这是推荐做法:定义一个全局异常处理器类,配合自定义响应体(如 Result<t></t>),覆盖常见异常类型。
- 定义统一返回类(例如):
public class Result<t> {<br>
private int code;<br>
private String msg;<br>
private T data;<br>
// 构造方法、getter/setter 略<br>
}</t>
- 编写全局异常处理器:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
@ControllerAdvice<br>
public class GlobalExceptionHandler {<br><br>
@ExceptionHandler(BusinessException.class)<br>
@ResponseBody<br>
public Result<void> handleBusinessException(BusinessException e) {<br>
return Result.fail(e.getCode(), e.getMessage());<br>
}<br><br>
@ExceptionHandler(MethodArgumentNotValidException.class)<br>
@ResponseBody<br>
public Result<void> handleValidationException(MethodArgumentNotValidException e) {<br>
String msg = e.getBindingResult().getFieldErrors().get(0).getDefaultMessage();<br>
return Result.fail(400, msg);<br>
}<br><br>
@ExceptionHandler(Exception.class)<br>
@ResponseBody<br>
public Result<void> handleUnexpectedException(Exception e) {<br>
log.error("未预期异常", e);<br>
return Result.fail(500, "服务内部错误");<br>
}<br>
}</void></void></void>
为什么不用 HandlerInterceptor 处理异常
拦截器的 afterCompletion 方法虽然能拿到 Exception 参数,但它只是“事后通知”,不能改变已产生的响应内容(比如 Controller 已返回 200 + 错误数据,或已抛出未被捕获的异常导致响应中断)。它适合做日志、监控、资源清理,不适合做异常响应封装。
- 拦截器中无法阻止默认错误页面(如 Whitelabel Error Page)
- 若 Controller 抛出异常且无 @ExceptionHandler,请求会直接交由 DispatcherServlet 的默认异常处理器,跳过拦截器的异常逻辑
- 响应体已被写入或提交后,再想修改 HTTP 状态码或 body 就无效了
进阶:配合 @ResponseStatus 和 ResponseEntity
对简单场景,可直接在自定义异常上加 @ResponseStatus 注解,Spring 会自动设置状态码;但若需动态状态码或统一 JSON 结构,仍应走 @ExceptionHandler 返回 ResponseEntity<result>></result>:
@ExceptionHandler(PermissionDeniedException.class)<br>
public ResponseEntity<result>> handlePermissionDenied() {<br>
Result<void> result = Result.fail(403, "权限不足");<br>
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(result);<br>
}</void></result>
补充:确保配置生效
确认你的项目满足以下条件:
- 类被 Spring 扫描到(在主启动类同包或子包下,或显式
@ComponentScan) - 使用了
@EnableWebMvc(不推荐)或依赖 Spring Boot Web Starter(自动配置) - 没有其他
HandlerExceptionResolverBean 覆盖默认行为(如自定义了SimpleMappingExceptionResolver)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










