在 Spring Boot 框架中,全局异常处理器(Global Exception Handler) 是一种集中处理应用程序中未被捕获的异常的机制。它基于 Spring MVC 的 @ControllerAdvice 和 @ExceptionHandler 注解实现,能够统一返回格式、提升系统健壮性与用户体验。
一、核心原理
1. 底层机制
- Spring MVC 在处理请求时,若 Controller 方法抛出异常且未被 try-catch 捕获,会将异常交给 HandlerExceptionResolver 处理。
- 默认的实现类
ExceptionHandlerExceptionResolver会扫描带有@ControllerAdvice的类,并调用其中匹配的@ExceptionHandler方法。 - 最终将异常转换为统一的 HTTP 响应(如 JSON 格式),避免暴露堆栈信息给前端。
2. 关键注解
| 注解 | 作用 |
|---|---|
@ControllerAdvice |
定义一个全局的异常处理类,作用于所有 @Controller 或 @RestController |
@RestControllerAdvice |
= @ControllerAdvice + @ResponseBody,直接返回 JSON(推荐用于 REST API) |
@ExceptionHandler |
标注在方法上,指定该方法处理哪些异常类型 |
二、使用方法(完整示例)
步骤 1:定义统一响应格式(可选但推荐)
// 统一返回结构
public class Result<T> {
private int code;
private String message;
private T data;
public static <T> Result<T> error(int code, String message) {
Result<T> result = new Result<>();
result.code = code;
result.message = message;
return result;
}
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.code = 200;
result.message = "success";
result.data = data;
return result;
}
// getter/setter 省略
}
步骤 2:创建全局异常处理器
import org.springframework.web.bind.annotation.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
@RestControllerAdvice // 全局异常处理 + 自动@ResponseBody
public class GlobalExceptionHandler {
// 1. 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public Result<String> handleBusinessException(BusinessException e) {
return Result.error(e.getCode(), e.getMessage());
}
// 2. 处理参数校验失败(JSR-303 / @Valid)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> handleValidationException(MethodArgumentNotValidException e) {
StringBuilder sb = new StringBuilder();
for (FieldError error : e.getBindingResult().getFieldErrors()) {
sb.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; ");
}
return Result.error(400, "参数校验失败: " + sb.toString());
}
// 3. 处理空指针异常(开发阶段常见)
@ExceptionHandler(NullPointerException.class)
public Result<String> handleNPE(NullPointerException e) {
// 生产环境不建议暴露具体错误
return Result.error(500, "服务器内部错误");
}
// 4. 处理通用异常(兜底)
@ExceptionHandler(Exception.class)
public Result<String> handleGenericException(Exception e) {
e.printStackTrace(); // 记录日志(实际应使用 SLF4J)
return Result.error(500, "系统繁忙,请稍后再试");
}
// 5. 处理特定 HTTP 状态码异常(如 404)
@ExceptionHandler(NoHandlerFoundException.class)
public Result<String> handle404(NoHandlerFoundException e) {
return Result.error(404, "接口不存在");
}
}
步骤 3:定义自定义业务异常(可选)
public class BusinessException extends RuntimeException {
private int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
// getter
public int getCode() { return code; }
}
步骤 4:在 Controller 中抛出异常
@RestController
@RequestMapping("/api/user")
public class UserController {
@PostMapping("/register")
public Result<String> register(@Valid @RequestBody UserDTO user) {
if ("admin".equals(user.getUsername())) {
throw new BusinessException(1001, "用户名已被禁止注册");
}
// ... 业务逻辑
return Result.success("注册成功");
}
}
步骤 5:启用 Spring Boot 对 404 的异常处理(重要!)
在 application.yml 中添加:
spring:
mvc:
throw-exception-if-no-handler-found: true
web:
resources:
add-mappings: false # 禁用静态资源处理,让 404 走异常处理器
否则 NoHandlerFoundException 不会触发。
三、执行流程图解
[HTTP Request]
↓
[Controller Method] → 抛出异常(如 BusinessException)
↓
Spring MVC 捕获异常
↓
查找 @ControllerAdvice 中匹配的 @ExceptionHandler
↓
执行 handleBusinessException()
↓
返回 Result 对象 → 自动序列化为 JSON
↓
[HTTP Response]
{
"code": 1001,
"message": "用户名已被禁止注册",
"data": null
}
四、注意事项
-
优先级 :
@ExceptionHandler方法越具体(如BusinessException),优先级越高;Exception.class是兜底。 -
日志记录 :
在
handleGenericException中应使用log.error("系统异常", e);而非printStackTrace()。 -
生产安全 :
切勿将
e.getMessage()或堆栈直接返回给前端,防止信息泄露。 -
异步支持 :
若使用
@Async,全局异常处理器不会生效 ,需单独处理(如实现AsyncUncaughtExceptionHandler)。 -
WebFlux(响应式) :
上述基于 Servlet,若用 WebFlux 需使用
@ControllerAdvice+WebExceptionHandler。
五、总结
| 优势 | 说明 |
|---|---|
| ✅ 统一错误格式 | 前端无需处理各种异常结构 |
| ✅ 解耦业务逻辑 | Controller 只关注业务,不写 try-catch |
| ✅ 提升可维护性 | 异常处理集中管理 |
| ✅ 增强安全性 | 避免敏感信息泄露 |
通过全局异常处理器,你的 Spring Boot 应用将具备更专业、稳定的 API 行为。建议结合 自定义异常 + 参数校验 + 日志监控 构建完整异常体系。