Spring Boot 统一异常处理与返回?

2025年 阅读约 15 分钟 面试指南 · Spring Boot

深入解析Spring Boot统一异常处理与返回:@ControllerAdvice全局异常处理、@ExceptionHandler、统一响应体封装Result、参数校验异常处理、自定义业务异常,附面试模拟问答。

一句话总结

Spring Boot 统一异常处理核心:@ControllerAdvice + @ExceptionHandler 全局拦截异常,配合 统一响应体 Result<T>(code + message + data)返回规范格式。处理层级:自定义业务异常 → 参数校验异常 → 系统异常兜底。关键点:@ExceptionHandler 优先级(子类异常优先匹配)、@ResponseBody 自动转 JSON、@Validated 校验异常统一处理。

初级理解

统一响应体

# 统一响应体封装 @Data @AllArgsConstructor @NoArgsConstructor public class Result<T> { private int code; // 状态码 private String message; // 提示信息 private T data; // 数据 public static <T> Result<T> success(T data) { return new Result<>(200, "success", data); } public static <T> Result<T> error(int code, String message) { return new Result<>(code, message, null); } } # Controller 使用 @RestController public class UserController { @GetMapping("/user/{id}") public Result<User> getUser(@PathVariable Long id) { User user = userService.getById(id); return Result.success(user); } } # 返回 JSON # {"code":200,"message":"success","data":{"id":1,"name":"张三"}}

中级深入

全局异常处理

# @ControllerAdvice 全局异常处理 @RestControllerAdvice // = @ControllerAdvice + @ResponseBody public class GlobalExceptionHandler { // 1. 处理自定义业务异常 @ExceptionHandler(BusinessException.class) public Result<Void> handleBusinessException(BusinessException e) { return Result.error(e.getCode(), e.getMessage()); } // 2. 处理参数校验异常 @ExceptionHandler(MethodArgumentNotValidException.class) public Result<Void> handleValidationException(MethodArgumentNotValidException e) { String message = e.getBindingResult() .getFieldErrors() .stream() .map(FieldError::getDefaultMessage) .collect(Collectors.joining(", ")); return Result.error(400, message); } // 3. 兜底处理未知异常 @ExceptionHandler(Exception.class) public Result<Void> handleException(Exception e) { log.error("系统异常", e); return Result.error(500, "系统繁忙,请稍后重试"); } }

自定义业务异常

# 自定义异常类 public class BusinessException extends RuntimeException { private int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(String message) { this(400, message); } } # 使用 @Service public class UserService { public User getById(Long id) { User user = userDao.selectById(id); if (user == null) { throw new BusinessException(404, "用户不存在"); } return user; } }

高级拓展

@ExceptionHandler 匹配规则

# 异常匹配优先级 # 1. 精确匹配:抛出的异常类型 == @ExceptionHandler 声明的类型 # 2. 子类匹配:抛出子类异常,匹配父类处理器 # 3. 最接近匹配:多个处理器都匹配时,选继承链最近的 # 示例 @ExceptionHandler(RuntimeException.class) public Result handleRuntime() { } // 处理器 A @ExceptionHandler(IllegalArgumentException.class) public Result handleIllegal() { } // 处理器 B # 抛出 IllegalArgumentException → 匹配 B(更精确) # 抛出 NullPointerException → 匹配 A(只有 A 能匹配)

参数校验统一处理

# DTO 参数校验 @Data public class UserDTO { @NotBlank(message = "用户名不能为空") private String username; @Email(message = "邮箱格式不正确") private String email; @Min(value = 18, message = "年龄不能小于18") @Max(value = 100, message = "年龄不能大于100") private int age; } # Controller @PostMapping("/user") public Result<Void> createUser(@Valid @RequestBody UserDTO dto) { userService.create(dto); return Result.success(null); } # 校验失败时抛出 MethodArgumentNotValidException # 由 GlobalExceptionHandler 统一处理

实战场景

场景:完整统一返回方案

# 1. 定义错误码枚举 public enum ErrorCode { SUCCESS(200, "成功"), BAD_REQUEST(400, "参数错误"), UNAUTHORIZED(401, "未登录"), FORBIDDEN(403, "无权限"), NOT_FOUND(404, "资源不存在"), SERVER_ERROR(500, "服务器错误"); private int code; private String message; } # 2. 统一响应体 @Data public class Result<T> { private int code; private String message; private T data; private long timestamp = System.currentTimeMillis(); public static <T> Result<T> success(T data) { Result<T> r = new Result<>(); r.code = ErrorCode.SUCCESS.getCode(); r.message = ErrorCode.SUCCESS.getMessage(); r.data = data; return r; } public static <T> Result<T> error(ErrorCode errorCode) { Result<T> r = new Result<>(); r.code = errorCode.getCode(); r.message = errorCode.getMessage(); return r; } }

面试模拟

面试官:Spring Boot 如何做统一异常处理?

你:使用 @RestControllerAdvice + @ExceptionHandler。定义 GlobalExceptionHandler 类,用 @ExceptionHandler 分别处理业务异常、参数校验异常、系统异常。配合统一响应体 Result,返回规范的 JSON 格式。

面试官:@ControllerAdvice 和 @ExceptionHandler 的原理?

你:@ControllerAdvice 本质是 AOP,它会被注册为全局的 Controller 增强。当 Controller 抛出异常时,DispatcherServlet 会查找匹配的 @ExceptionHandler 方法,按异常类型精确匹配,找到后调用并返回结果。