Spring Boot 全局异常处理:@ControllerAdvice 实战

详细介绍 Spring Boot 全局异常处理的实现方式,包括 @ControllerAdvice、@ExceptionHandler 的使用。

Java 后端 2026-06-14 10 分钟

Spring Boot 全局异常处理:@ControllerAdvice 实战

统一的异常处理是 REST API 的基本要求。本文介绍 Spring Boot 全局异常处理的实现。

为什么需要全局异常处理?

  1. 统一响应格式:所有错误返回相同格式
  2. 集中管理:异常处理逻辑集中在一个地方
  3. 安全性:避免泄露内部错误信息

@ControllerAdvice

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    // 处理业务异常
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusiness(BusinessException e) {
        return ResponseEntity.status(e.getCode())
            .body(new ErrorResponse(e.getCode(), e.getMessage()));
    }
    
    // 处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(err -> err.getField() + ": " + err.getDefaultMessage())
            .collect(Collectors.joining(", "));
        return ResponseEntity.badRequest()
            .body(new ErrorResponse(400, message));
    }
    
    // 处理未找到异常
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException e) {
        return ResponseEntity.status(404)
            .body(new ErrorResponse(404, e.getMessage()));
    }
    
    // 处理所有其他异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e) {
        return ResponseEntity.status(500)
            .body(new ErrorResponse(500, "服务器内部错误"));
    }
}

自定义业务异常

public class BusinessException extends RuntimeException {
    private final int code;
    
    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }
    
    public BusinessException(String message) {
        this(400, message);
    }
    
    public int getCode() { return code; }
}

统一响应格式

public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "success", data);
    }
    
    public static ApiResponse<?> error(int code, String message) {
        return new ApiResponse<>(code, message, null);
    }
}

使用示例

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @GetMapping("/{id}")
    public ApiResponse<User> findById(@PathVariable Long id) {
        User user = userService.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("用户不存在"));
        return ApiResponse.success(user);
    }
    
    @PostMapping
    public ApiResponse<User> create(@Valid @RequestBody UserDTO dto) {
        User user = userService.create(dto);
        return ApiResponse.success(user);
    }
}

最佳实践

  1. 分层处理:业务异常、参数异常、系统异常分别处理
  2. 统一格式:所有响应使用相同格式
  3. 日志记录:记录异常日志,方便排查
  4. 安全考虑:不要泄露内部错误信息

总结

全局异常处理是 REST API 的基本要求。通过 @ControllerAdvice 和 @ExceptionHandler,可以实现统一的异常处理。

📚 相关文章