以下是不同场景下的具体方法:
方法 1:直接使用 @ResponseStatus
注解
在 Controller 方法或异常类上使用 @ResponseStatus
注解,直接指定返回的状态码。
场景示例:固定返回指定状态码
java
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
// 成功创建资源时返回 201
@PostMapping("/create")
@ResponseStatus(HttpStatus.CREATED) // 状态码 201
public String createResource() {
return "Resource created";
}
}
方法 2:动态返回 ResponseEntity
对象
通过 ResponseEntity
对象在代码中动态控制状态码,适用于需要根据业务逻辑返回不同状态码的场景。
场景示例:根据条件返回不同状态码
java
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/user/{id}")
public ResponseEntity<String> getUser(@PathVariable Long id) {
if (id == 1) {
return ResponseEntity.ok("User found"); // 默认 200
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found"); // 404
}
}
}
方法 3:通过全局异常处理统一修改状态码
使用 @ControllerAdvice
和 @ExceptionHandler
拦截异常并统一设置状态码。
场景示例:资源不存在时返回 404
java
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import javax.persistence.EntityNotFoundException;
@ControllerAdvice
public class GlobalExceptionHandler {
// 捕获 EntityNotFoundException 并返回 404
@ExceptionHandler(EntityNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleEntityNotFound() {
return "Resource not found";
}
}
方法 4:直接操作 HttpServletResponse
在 Controller 方法中注入 HttpServletResponse
对象,直接设置状态码。
场景示例:手动设置状态码
java
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/manual")
public String manualStatus(HttpServletResponse response) {
response.setStatus(HttpStatus.ACCEPTED.value()); // 状态码 202
return "Status manually set";
}
}
常见场景与状态码对照表
场景 | 推荐状态码 | 说明 |
---|---|---|
成功 | 200 OK | 默认成功状态码 |
创建资源成功 | 201 Created | 配合 @PostMapping 使用 |
请求参数错误 | 400 Bad Request | 客户端请求错误 |
未授权访问 | 401 Unauthorized | 需要身份验证 |
禁止访问 | 403 Forbidden | 无权限访问资源 |
资源不存在 | 404 Not Found | 请求的资源不存在 |
服务器内部错误 | 500 Internal Error | 未捕获的异常导致服务器错误 |
注意事项
-
优先级问题
ResponseEntity
的优先级高于@ResponseStatus
,如果二者同时存在,以ResponseEntity
为准。 -
直接操作
HttpServletResponse
的限制如果在设置状态码后修改响应体,可能导致
IllegalStateException
,建议优先使用 Spring 提供的抽象(如ResponseEntity
)。 -
全局异常处理的覆盖范围
通过
@ControllerAdvice
可以统一处理所有 Controller 抛出的异常,适合集中管理错误状态码。
通过上述方法,你可以根据具体场景灵活控制 HTTP 响应的状态码。推荐优先使用 ResponseEntity
或 @ResponseStatus
保持代码简洁。
以下是结合自定义返回工具类与 Spring Boot 状态码控制的详细方案,提供代码示例和分步说明:
1. 定义统一返回结果工具类
java
public class ApiResponse<T> {
private int code; // 业务状态码(非 HTTP 状态码)
private String message; // 提示信息
private T data; // 返回数据
// 快速创建成功响应(静态工厂方法)
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(200, "Success", data);
}
// 快速创建失败响应(链式调用支持)
public static ApiResponse<Void> failure(int code, String message) {
return new ApiResponse<>(code, message, null);
}
public ApiResponse<T> code(int code) {
this.code = code;
return this;
}
public ApiResponse<T> message(String message) {
this.message = message;
return this;
}
// 构造方法、Getter 省略...
}
2. 与状态码控制方法结合使用
场景 1:固定状态码 + 统一数据结构(@ResponseStatus)
java
@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED) // 强制 HTTP 201
public ApiResponse<User> createUser(@RequestBody User user) {
User savedUser = userService.save(user);
return ApiResponse.success(savedUser)
.message("User created successfully");
}
场景 2:动态状态码 + 统一数据结构(ResponseEntity)
java
@GetMapping("/products/{id}")
public ResponseEntity<ApiResponse<Product>> getProduct(@PathVariable Long id) {
return productService.findById(id)
.map(product ->
ResponseEntity.ok(ApiResponse.success(product)) // HTTP 200
)
.orElseGet(() ->
ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.failure(404, "Product not found"))
);
}
3. 全局异常处理统一包装结果
java
@ControllerAdvice
public class GlobalExceptionHandler {
// 处理业务异常(HTTP 400 + 自定义错误码)
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ApiResponse<Void>> handleBusinessException(BusinessException ex) {
return ResponseEntity.badRequest() // HTTP 400
.body(ApiResponse.failure(ex.getCode(), ex.getMessage()));
}
// 处理资源不存在(HTTP 404)
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ApiResponse<Void>> handleResourceNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.failure(404, ex.getMessage()));
}
// 兜底异常处理(HTTP 500)
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Void>> handleGlobalException(Exception ex) {
return ResponseEntity.internalServerError()
.body(ApiResponse.failure(500, "Internal server error"));
}
}
4. 进阶工具类(支持链式设置 HTTP 状态码)
java
public class ApiResponseBuilder<T> {
private HttpStatus httpStatus = HttpStatus.OK; // 默认 200
private ApiResponse<T> apiResponse;
private ApiResponseBuilder(ApiResponse<T> apiResponse) {
this.apiResponse = apiResponse;
}
public static <T> ApiResponseBuilder<T> success(T data) {
return new ApiResponseBuilder<>(ApiResponse.success(data));
}
public ApiResponseBuilder<T> httpStatus(HttpStatus status) {
this.httpStatus = status;
return this;
}
public ResponseEntity<ApiResponse<T>> build() {
return ResponseEntity.status(httpStatus).body(apiResponse);
}
}
// 使用示例
@PostMapping("/orders")
public ResponseEntity<ApiResponse<Order>> createOrder() {
Order newOrder = orderService.create();
return ApiResponseBuilder.success(newOrder)
.httpStatus(HttpStatus.CREATED) // 设置 HTTP 201
.build();
}
5. 关键注意事项
-
明确区分两类状态码
HTTP 状态码
:描述网络请求结果(200/404/500)业务状态码
:描述业务逻辑结果(如 1001=库存不足)
-
推荐优先级
- 优先使用
ResponseEntity
控制 HTTP 状态码 - 使用工具类封装业务状态码
- 优先使用
-
保持响应结构一致性
json// 成功示例 { "code": 200, "message": "Success", "data": { "id": 1, "name": "test" } } // 错误示例(HTTP 404) { "code": 40401, "message": "Product not found", "data": null }
通过这种方式,您既可以精准控制 HTTP 协议层的状态码,又能通过工具类统一业务响应格式,同时保持代码的高度可维护性。