Spring Boot 3 构建统一的请求响应参数、异常处理、以及统一的异常状态码
在 Spring Boot 3 微服务中,构建统一的请求响应参数、异常处理、以及统一的异常状态码是标准化和提高可维护性的关键。以下是实现的最佳实践:
1. 统一请求响应结构
定义统一的响应结构
创建一个通用的响应包装类 ApiResponse:
public class ApiResponse<T> {
private int code; // 状态码
private String message; // 消息
private T data; // 数据
public ApiResponse(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(200, "Success", data);
}
public static <T> ApiResponse<T> success(String message, T data) {
return new ApiResponse<>(200, message, data);
}
public static <T> ApiResponse<T> error(int code, String message) {
return new ApiResponse<>(code, message, null);
}
// Getters and Setters
}
统一返回格式的切面处理
使用 Spring 的 @ControllerAdvice 对所有 @RestController 返回的内容进行统一封装:
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class GlobalResponseHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiResponse<Object> handleException(Exception ex) {
return ApiResponse.error(500, "Internal Server Error: " + ex.getMessage());
}
@ExceptionHandler(CustomException.class)
@ResponseBody
public ApiResponse<Object> handleCustomException(CustomException ex) {
return ApiResponse.error(ex.getCode(), ex.getMessage());
}
}
2. 统一异常处理
自定义异常类
创建一个通用的业务异常类 CustomException:
public class CustomException extends RuntimeException {
private int code;
public CustomException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}
全局异常处理
在 @RestControllerAdvice 中捕获自定义异常和其他常见异常:
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomException.class)
public ApiResponse<Object> handleCustomException(CustomException ex) {
return ApiResponse.error(ex.getCode(), ex.getMessage());
}
@ExceptionHandler(IllegalArgumentException.class)
public ApiResponse<Object> handleIllegalArgumentException(IllegalArgumentException ex) {
return ApiResponse.error(400, "Invalid Argument: " + ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ApiResponse<Object> handleGeneralException(Exception ex) {
return ApiResponse.error(500, "Internal Server Error: " + ex.getMessage());
}
}
3. 统一状态码管理
定义状态码枚举
创建一个枚举类,管理所有可能的状态码:
public enum ApiStatus {
SUCCESS(200, "Success"),
BAD_REQUEST(400, "Bad Request"),
UNAUTHORIZED(401, "Unauthorized"),
FORBIDDEN(403, "Forbidden"),
NOT_FOUND(404, "Not Found"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
CUSTOM_ERROR(1001, "Custom Business Error");
private final int code;
private final String message;
ApiStatus(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
在 CustomException 中使用状态码
public class CustomException extends RuntimeException {
private int code;
public CustomException(ApiStatus status) {
super(status.getMessage());
this.code = status.getCode();
}
public int getCode() {
return code;
}
}
4. Controller 示例
在 Controller 中使用统一的返回结构和异常处理:
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user/{id}")
public ApiResponse<User> getUser(@PathVariable Long id) {
if (id <= 0) {
throw new CustomException(ApiStatus.BAD_REQUEST);
}
// 模拟用户数据
User user = new User(id, "John Doe", "john.doe@example.com");
return ApiResponse.success(user);
}
}
6. 总结
核心实现步骤:
统一响应格式:
定义 ApiResponse。
使用 @RestControllerAdvice 封装统一响应。
统一异常处理:
创建自定义异常类 CustomException。
使用全局异常处理器 @RestControllerAdvice 捕获异常。
统一状态码管理:
定义枚举类 ApiStatus。
使用状态码驱动异常和响应。