Spring Boot HTTP状态码详解
Spring Boot HTTP状态码完全指南:从入门到精通
前言
在RESTful API开发中,HTTP状态码是与客户端通信的重要桥梁。Spring Boot通过HttpStatus
枚举提供了完整的HTTP状态码支持。本文将深入解析这些状态码的含义、使用场景以及在Spring Boot中的最佳实践。
1. 信息响应 (100-199) - 请求处理中
1.1 CONTINUE (100)
- 含义:客户端应继续发送请求的剩余部分
- 使用场景:当客户端发送Expect: 100-continue头时,服务器确认可以接收请求体
- Spring Boot示例:大文件上传时的预检确认
1.2 SWITCHING_PROTOCOLS (101)
- 含义:服务器同意客户端请求,切换协议
- 使用场景:WebSocket连接升级、HTTP/2协议切换
1.3 PROCESSING (102)
- 含义:服务器已收到请求,正在处理但尚未完成
- 使用场景:长时间运行的操作,如大数据处理
1.4 EARLY_HINTS (103)
- 含义:用于在最终响应之前发送一些HTTP头
- 使用场景:预加载资源,优化页面加载性能
2. 成功响应 (200-299) - 请求成功处理
2.1 OK (200) ✅
- 含义:请求成功
- 使用场景:GET请求成功返回数据
- Spring Boot示例:
@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {User user = userService.findById(id);return ResponseEntity.ok(user); // 返回200状态码
}
2.2 CREATED (201) 🆕
- 含义:资源创建成功
- 使用场景:POST请求创建新资源
- 最佳实践:应在响应头中包含新资源的Location
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {User savedUser = userService.save(user);return ResponseEntity.created(URI.create("/users/" + savedUser.getId())).body(savedUser);
}
2.3 ACCEPTED (202) ⏳
- 含义:请求已接受,但处理尚未完成
- 使用场景:异步操作,如批量处理、邮件发送
2.4 NO_CONTENT (204) 🚫
- 含义:请求成功,但无内容返回
- 使用场景:DELETE操作成功、UPDATE操作无需返回数据
@DeleteMapping("/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {userService.deleteById(id);return ResponseEntity.noContent().build(); // 返回204
}
2.5 PARTIAL_CONTENT (206) 📦
- 含义:部分内容请求成功
- 使用场景:分片下载、断点续传
3. 重定向响应 (300-399) - 需要进一步操作
3.1 MOVED_PERMANENTLY (301) 🔄
- 含义:资源已永久移动到新位置
- 使用场景:网站改版、API版本迁移
3.2 FOUND (302) 🔍
- 含义:资源临时移动到其他位置
- 使用场景:临时重定向,如登录后跳转
3.3 SEE_OTHER (303) 👀
- 含义:查看其他URI获取响应
- 使用场景:POST成功后重定向到GET请求
3.4 NOT_MODIFIED (304) 📄
- 含义:资源未修改,可使用缓存版本
- 使用场景:配合If-Modified-Since或ETag使用
4. 客户端错误 (400-499) - 客户端请求有问题
4.1 BAD_REQUEST (400) ❌
- 含义:请求语法错误或参数无效
- 使用场景:参数验证失败、JSON格式错误
- Spring Boot验证示例:
@PostMapping("/users")
public ResponseEntity<?> createUser(@Valid @RequestBody UserCreateRequest request) {// 自动验证,失败返回400userService.create(request);return ResponseEntity.ok().build();
}
4.2 UNAUTHORIZED (401) 🔐
- 含义:需要身份验证
- 使用场景:未提供认证信息或认证失败
4.3 FORBIDDEN (403) ⚠️
- 含义:服务器理解请求但拒绝执行
- 使用场景:权限不足、IP限制
4.4 NOT_FOUND (404) 🔍
- 含义:请求的资源不存在
- 使用场景:访问不存在的URL或资源ID
@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {return userService.findById(id).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build()); // 返回404
}
4.5 METHOD_NOT_ALLOWED (405) 🚷
- 含义:请求方法不被允许
- 使用场景:对只读资源执行POST操作
4.6 UNPROCESSABLE_ENTITY (422) 📝
- 含义:请求格式正确但语义错误
- 使用场景:业务规则验证失败,如邮箱已注册
4.7 TOO_MANY_REQUESTS (429) 🚦
- 含义:请求频率过高
- 使用场景:API限流、防刷机制
5. 服务器错误 (500-599) - 服务器处理失败
5.1 INTERNAL_SERVER_ERROR (500) 💥
- 含义:服务器内部错误
- 使用场景:未捕获的异常、数据库连接失败
- Spring Boot异常处理:
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<ApiResponse<?>> handleException(Exception e) {log.error("服务器异常", e);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ApiResponse.error(500, "系统繁忙,请稍后重试"));}
}
5.2 NOT_IMPLEMENTED (501) 🔧
- 含义:服务器不支持请求的功能
- 使用场景:未实现的API端点
5.3 BAD_GATEWAY (502) 🌐
- 含义:网关或代理服务器从上游服务器收到无效响应
- 使用场景:微服务调用失败
5.4 SERVICE_UNAVAILABLE (503) ⚡
- 含义:服务暂时不可用
- 使用场景:系统维护、过载保护
5.5 GATEWAY_TIMEOUT (504) ⏰
- 含义:网关超时
- 使用场景:上游服务响应超时
6. Spring Boot中的最佳实践
6.1 使用ResponseEntity精确控制状态码
@GetMapping("/custom")
public ResponseEntity<String> customResponse() {if (someCondition) {return ResponseEntity.status(HttpStatus.CREATED).body("Created");} else {return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Not Found");}
}
6.2 统一的错误响应格式
@Data
public class ErrorResponse {private int status;private String error;private String message;private String path;private LocalDateTime timestamp;public ErrorResponse(HttpStatus status, String message, String path) {this.status = status.value();this.error = status.getReasonPhrase();this.message = message;this.path = path;this.timestamp = LocalDateTime.now();}
}
6.3 状态码选择指南
操作类型 | 成功状态码 | 失败状态码 |
---|---|---|
查询(GET) | 200 OK | 404 Not Found |
创建(POST) | 201 Created | 400 Bad Request |
更新(PUT) | 200 OK | 404 Not Found |
删除(DELETE) | 204 No Content | 404 Not Found |
部分更新(PATCH) | 200 OK | 400 Bad Request |
7. 常见问题解答
Q: 什么时候使用200 vs 204?
A: 当需要返回数据时用200,不需要返回数据时用204。
Q: 401和403的区别?
A: 401表示未认证(需要登录),403表示已认证但权限不足。
Q: 400和422的区别?
A: 400表示请求语法错误,422表示语法正确但业务逻辑错误。
8. 总结
正确地使用HTTP状态码是构建高质量RESTful API的关键。Spring Boot的HttpStatus
枚举为我们提供了完整的支持:
- 信息类状态码用于通信协商
- 成功类状态码表示操作成功
- 重定向类状态码处理资源位置变更
- 客户端错误类状态码帮助客户端纠正请求
- 服务器错误类状态码表示服务端问题
通过合理选择状态码并提供清晰的错误信息,可以大大提升API的可用性和开发者体验。
9. 完整HTTP状态码参考表格
以下是Spring Boot中HttpStatus
枚举包含的所有状态码的完整参考表格:
状态码 | 枚举常量 | 状态系列 | 含义描述 | 使用场景 |
---|---|---|---|---|
100 | CONTINUE | INFORMATIONAL | 继续 | 客户端应继续发送请求的剩余部分 |
101 | SWITCHING_PROTOCOLS | INFORMATIONAL | 切换协议 | WebSocket连接升级、HTTP/2协议切换 |
102 | PROCESSING | INFORMATIONAL | 处理中 | 长时间运行的操作,如大数据处理 |
103 | EARLY_HINTS | INFORMATIONAL | 早期提示 | 预加载资源,优化页面加载性能 |
103 | CHECKPOINT | INFORMATIONAL | 检查点(已弃用) | 已弃用,使用EARLY_HINTS替代 |
200 | OK | SUCCESSFUL | 成功 | GET请求成功返回数据 |
201 | CREATED | SUCCESSFUL | 已创建 | POST请求创建新资源 |
202 | ACCEPTED | SUCCESSFUL | 已接受 | 异步操作,如批量处理 |
203 | NON_AUTHORITATIVE_INFORMATION | SUCCESSFUL | 非权威信息 | 代理服务器修改了响应 |
204 | NO_CONTENT | SUCCESSFUL | 无内容 | DELETE操作成功、UPDATE操作无需返回数据 |
205 | RESET_CONTENT | SUCCESSFUL | 重置内容 | 客户端需要重置文档视图 |
206 | PARTIAL_CONTENT | SUCCESSFUL | 部分内容 | 分片下载、断点续传 |
207 | MULTI_STATUS | SUCCESSFUL | 多状态 | WebDAV扩展,多个操作状态 |
208 | ALREADY_REPORTED | SUCCESSFUL | 已报告 | WebDAV,成员已在之前报告中 |
226 | IM_USED | SUCCESSFUL | IM已使用 | 服务器已对请求进行了实例操作 |
300 | MULTIPLE_CHOICES | REDIRECTION | 多种选择 | 请求的资源有多个表示形式 |
301 | MOVED_PERMANENTLY | REDIRECTION | 永久移动 | 资源已永久移动到新位置 |
302 | FOUND | REDIRECTION | 临时移动 | 资源临时移动到其他位置 |
302 | MOVED_TEMPORARILY | REDIRECTION | 临时移动(已弃用) | 已弃用,使用FOUND替代 |
303 | SEE_OTHER | REDIRECTION | 查看其他 | POST成功后重定向到GET请求 |
304 | NOT_MODIFIED | REDIRECTION | 未修改 | 资源未修改,可使用缓存版本 |
305 | USE_PROXY | REDIRECTION | 使用代理(已弃用) | 已弃用 |
307 | TEMPORARY_REDIRECT | REDIRECTION | 临时重定向 | 请求应使用另一个URI重复 |
308 | PERMANENT_REDIRECT | REDIRECTION | 永久重定向 | 请求和所有未来请求应使用另一个URI |
400 | BAD_REQUEST | CLIENT_ERROR | 错误请求 | 请求语法错误或参数无效 |
401 | UNAUTHORIZED | CLIENT_ERROR | 未授权 | 需要身份验证 |
402 | PAYMENT_REQUIRED | CLIENT_ERROR | 需要付款 | 保留用于未来支付系统 |
403 | FORBIDDEN | CLIENT_ERROR | 禁止访问 | 权限不足、IP限制 |
404 | NOT_FOUND | CLIENT_ERROR | 未找到 | 请求的资源不存在 |
405 | METHOD_NOT_ALLOWED | CLIENT_ERROR | 方法不允许 | 请求方法不被允许 |
406 | NOT_ACCEPTABLE | CLIENT_ERROR | 不可接受 | 服务器无法生成客户端接受的内容 |
407 | PROXY_AUTHENTICATION_REQUIRED | CLIENT_ERROR | 需要代理认证 | 代理服务器需要认证 |
408 | REQUEST_TIMEOUT | CLIENT_ERROR | 请求超时 | 服务器等待请求超时 |
409 | CONFLICT | CLIENT_ERROR | 冲突 | 请求与当前资源状态冲突 |
410 | GONE | CLIENT_ERROR | 已删除 | 资源已永久删除 |
411 | LENGTH_REQUIRED | CLIENT_ERROR | 需要长度 | 需要Content-Length头 |
412 | PRECONDITION_FAILED | CLIENT_ERROR | 前提条件失败 | 请求头中前提条件失败 |
413 | PAYLOAD_TOO_LARGE | CLIENT_ERROR | 负载过大 | 请求实体过大 |
413 | REQUEST_ENTITY_TOO_LARGE | CLIENT_ERROR | 请求实体过大(已弃用) | 已弃用,使用PAYLOAD_TOO_LARGE |
414 | URI_TOO_LONG | CLIENT_ERROR | URI过长 | 请求URI过长 |
414 | REQUEST_URI_TOO_LONG | CLIENT_ERROR | 请求URI过长(已弃用) | 已弃用,使用URI_TOO_LONG |
415 | UNSUPPORTED_MEDIA_TYPE | CLIENT_ERROR | 不支持的媒体类型 | 不支持的媒体格式 |
416 | REQUESTED_RANGE_NOT_SATISFIABLE | CLIENT_ERROR | 请求范围不可满足 | 无法满足请求的范围 |
417 | EXPECTATION_FAILED | CLIENT_ERROR | 期望失败 | 无法满足Expect请求头 |
418 | I_AM_A_TEAPOT | CLIENT_ERROR | 我是茶壶 | HTTP愚人节笑话,实际不使用 |
419 | INSUFFICIENT_SPACE_ON_RESOURCE | CLIENT_ERROR | 资源空间不足(已弃用) | 已弃用 |
420 | METHOD_FAILURE | CLIENT_ERROR | 方法失败(已弃用) | 已弃用 |
421 | DESTINATION_LOCKED | CLIENT_ERROR | 目标锁定(已弃用) | 已弃用 |
422 | UNPROCESSABLE_ENTITY | CLIENT_ERROR | 不可处理的实体 | 请求格式正确但语义错误 |
423 | LOCKED | CLIENT_ERROR | 已锁定 | 资源被锁定 |
424 | FAILED_DEPENDENCY | CLIENT_ERROR | 依赖失败 | WebDAV,依赖的操作失败 |
425 | TOO_EARLY | CLIENT_ERROR | 太早 | 服务器不愿意处理可能重放的请求 |
426 | UPGRADE_REQUIRED | CLIENT_ERROR | 需要升级 | 客户端应切换到不同的协议 |
428 | PRECONDITION_REQUIRED | CLIENT_ERROR | 需要前提条件 | 需要条件性请求 |
429 | TOO_MANY_REQUESTS | CLIENT_ERROR | 请求过多 | API限流、防刷机制 |
431 | REQUEST_HEADER_FIELDS_TOO_LARGE | CLIENT_ERROR | 请求头字段过大 | 请求头字段太大 |
451 | UNAVAILABLE_FOR_LEGAL_REASONS | CLIENT_ERROR | 因法律原因不可用 | 因法律要求无法提供 |
500 | INTERNAL_SERVER_ERROR | SERVER_ERROR | 内部服务器错误 | 服务器内部错误 |
501 | NOT_IMPLEMENTED | SERVER_ERROR | 未实现 | 服务器不支持请求的功能 |
502 | BAD_GATEWAY | SERVER_ERROR | 错误网关 | 网关或代理服务器收到无效响应 |
503 | SERVICE_UNAVAILABLE | SERVER_ERROR | 服务不可用 | 系统维护、过载保护 |
504 | GATEWAY_TIMEOUT | SERVER_ERROR | 网关超时 | 上游服务响应超时 |
505 | HTTP_VERSION_NOT_SUPPORTED | SERVER_ERROR | HTTP版本不支持 | 不支持的HTTP协议版本 |
506 | VARIANT_ALSO_NEGOTIATES | SERVER_ERROR | 变体也可协商 | 透明内容协商中的循环引用 |
507 | INSUFFICIENT_STORAGE | SERVER_ERROR | 存储空间不足 | WebDAV,存储空间不足 |
508 | LOOP_DETECTED | SERVER_ERROR | 检测到循环 | WebDAV,检测到无限循环 |
509 | BANDWIDTH_LIMIT_EXCEEDED | SERVER_ERROR | 带宽限制超出 | 带宽使用超出限制 |
510 | NOT_EXTENDED | SERVER_ERROR | 未扩展 | 需要进一步扩展才能完成请求 |
511 | NETWORK_AUTHENTICATION_REQUIRED | SERVER_ERROR | 需要网络认证 | 需要网络认证才能访问 |
表格说明:
-
状态码系列说明:
- INFORMATIONAL (100-199): 信息响应,请求处理中
- SUCCESSFUL (200-299): 成功响应,请求成功处理
- REDIRECTION (300-399): 重定向响应,需要进一步操作
- CLIENT_ERROR (400-499): 客户端错误,客户端请求有问题
- SERVER_ERROR (500-599): 服务器错误,服务器处理失败
-
已弃用状态码: 表格中标记为"已弃用"的状态码不建议在新项目中使用
-
常用状态码: 在实际开发中,最常用的状态码包括:200, 201, 204, 400, 401, 403, 404, 500
希望本文能帮助您更好地理解和使用Spring Boot中的HTTP状态码。如有疑问,欢迎留言讨论!