HTTP 常用请求方法详解
HTTP 定义了一组请求方法,用来表示对资源的操作意图。Spring MVC 的 @RequestMapping(method = ...) 和 @GetMapping、@PostMapping 等注解,就是围绕这些方法设计的。
一、最常用的五个方法
| 方法 | 语义 | 是否有请求体 | 幂等 | 安全 |
|---|---|---|---|---|
| GET | 查询资源 | 否 | ✅ | ✅ |
| POST | 创建资源 / 提交数据 | 是 | ❌ | ❌ |
| PUT | 全量更新资源 | 是 | ✅ | ❌ |
| PATCH | 部分更新资源 | 是 | ❌ | ❌ |
| DELETE | 删除资源 | 通常无 | ✅ | ❌ |
幂等 :执行一次和执行多次,对资源的状态影响相同。
安全:不会修改资源状态。
二、GET
用于获取资源,是最常见的方法。
GET /users 查询用户列表
GET /users/1 查询 id 为 1 的用户
GET /users?name=张三 按条件查询
特点:
- 参数放在 URL 的查询字符串中,不在请求体里。
- 可以被浏览器缓存、收藏、分享。
- 有长度限制(取决于浏览器和服务器)。
- 不应产生副作用。
Spring MVC 对应:
java
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) { }
三、POST
用于创建资源或提交数据。
POST /users 创建用户,请求体包含用户信息
POST /login 提交登录表单
特点:
- 数据放在请求体中,不在 URL 里。
- 没有长度限制(理论上)。
- 不会被缓存,不能直接收藏。
- 非幂等:重复提交会创建多条记录。
Spring MVC 对应:
java
@PostMapping("/users")
public User createUser(@RequestBody User user) { }
四、PUT
用于全量更新资源。客户端提供资源的完整表示,服务器用这个表示替换原资源。
PUT /users/1 用请求体中的完整用户信息替换 id 为 1 的用户
特点:
- 幂等:同样的请求执行多次,结果一致。
- 如果资源不存在,有些实现会创建,有些会返回 404。
- 必须提供完整字段,未提供的字段通常被置空或重置为默认值。
Spring MVC 对应:
java
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) { }
五、PATCH
用于部分更新资源。只更新请求体中提供的字段,其他字段保持不变。
PATCH /users/1 只更新请求体中出现的字段,比如只改 email
特点:
- 非幂等(取决于实现),因为每次补丁可能基于当前状态。
- 比 PUT 更灵活,适合只改部分字段的场景。
Spring MVC 对应:
java
@PatchMapping("/users/{id}")
public User patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) { }
PUT 和 PATCH 的区别:
| 对比 | PUT | PATCH |
|---|---|---|
| 更新范围 | 全量替换 | 部分更新 |
| 请求体 | 完整资源表示 | 只包含要改的字段 |
| 幂等 | 是 | 通常不是 |
| 适用场景 | 整体覆盖 | 局部修改 |
六、DELETE
用于删除资源。
DELETE /users/1 删除 id 为 1 的用户
特点:
- 幂等:删除不存在的资源通常也返回成功(或 404,取决于实现)。
- 通常没有请求体。
Spring MVC 对应:
java
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) { }
七、其他方法
| 方法 | 用途 | 说明 |
|---|---|---|
| HEAD | 获取响应头,不要响应体 | 用于检查资源是否存在、是否被修改 |
| OPTIONS | 查询服务器支持的方法 | CORS 预检请求会用到 |
| TRACE | 回显请求 | 调试用,生产环境通常禁用 |
| CONNECT | 建立隧道 | 用于代理,如 HTTPS 代理 |
八、GET 和 POST 的核心区别
这是面试最常问的对比。
| 对比维度 | GET | POST |
|---|---|---|
| 参数位置 | URL 查询字符串 | 请求体 |
| 可见性 | 参数暴露在 URL 中 | 参数在请求体中,相对隐蔽 |
| 长度限制 | 受 URL 长度限制 | 理论上无限制 |
| 缓存 | 可被缓存 | 默认不缓存 |
| 收藏/分享 | 可以直接收藏 | 不能直接收藏 |
| 幂等 | 是 | 否 |
| 安全性 | 不应传输敏感信息 | 可以传输敏感信息(配合 HTTPS) |
| 典型用途 | 查询 | 创建、提交 |
注意:GET 和 POST 在传输层面都是明文(除非用 HTTPS),安全性差异不在于方法本身,而在于参数是否暴露在 URL、是否会被浏览器历史记录和服务器日志记录。
九、RESTful 风格中的方法使用
RESTful 设计的核心思想是:用 URL 表示资源,用 HTTP 方法表示操作。
| 操作 | 传统写法 | RESTful 写法 |
|---|---|---|
| 查询列表 | GET /getUserList |
GET /users |
| 查询单个 | GET /getUser?id=1 |
GET /users/1 |
| 创建 | POST /addUser |
POST /users |
| 更新 | POST /updateUser |
PUT /users/1 |
| 删除 | GET /deleteUser?id=1 |
DELETE /users/1 |
RESTful 风格下,URL 只表示资源,方法表示动作。同样的 /users/1,GET 是查询,PUT 是更新,DELETE 是删除。
十、Spring MVC 注解对应表
| HTTP 方法 | Spring 注解 | 等价写法 |
|---|---|---|
| GET | @GetMapping |
@RequestMapping(method = RequestMethod.GET) |
| POST | @PostMapping |
@RequestMapping(method = RequestMethod.POST) |
| PUT | @PutMapping |
@RequestMapping(method = RequestMethod.PUT) |
| DELETE | @DeleteMapping |
@RequestMapping(method = RequestMethod.DELETE) |
| PATCH | @PatchMapping |
@RequestMapping(method = RequestMethod.PATCH) |
十一、常见问题
1. 浏览器表单只支持 GET 和 POST
HTML 的 <form> 标签 method 属性只支持 GET 和 POST。如果要发送 PUT 或 DELETE,需要:
- 用 JavaScript 的
fetch或axios发送。 - 用隐藏字段
_method配合HiddenHttpMethodFilter(Spring 提供)。
2. GET 请求不要修改数据
GET 应该是安全的、幂等的。用 GET 执行删除或修改,违反了 HTTP 语义,可能导致爬虫、预加载、缓存等机制误触发写操作。
3. POST 不幂等,需要防重复提交
网络超时后客户端重试,可能创建多条记录。解决方案:前端防抖、后端幂等 token、数据库唯一约束。
4. PUT 和 PATCH 的选择
如果客户端能提供完整资源,用 PUT;如果只想改部分字段,用 PATCH。实际项目中 PUT 更常用,很多团队用 PUT 做部分更新,严格来说不符合语义,但约定俗成。
十二、总结
| 方法 | 一句话说明 | 幂等 | Spring 注解 |
|---|---|---|---|
| GET | 查询资源 | ✅ | @GetMapping |
| POST | 创建资源 / 提交数据 | ❌ | @PostMapping |
| PUT | 全量更新 | ✅ | @PutMapping |
| PATCH | 部分更新 | ❌ | @PatchMapping |
| DELETE | 删除资源 | ✅ | @DeleteMapping |
HTTP 方法的核心是语义:GET 查、POST 建、PUT 改、DELETE 删。RESTful 风格把这种语义发挥到极致,URL 只表示资源,方法表示动作。Spring MVC 的派生注解直接对应这些方法,让代码和 HTTP 语义保持一致。理解每个方法的幂等性和安全性,才能设计出符合规范的接口。