HTTP方法
HTTP方法(GET、DELETE、PUT、PATCH、POST)
第一层:基础认知(CRUD 标准映射)
这是最基础的,你肯定知道,但面试时要快速、准确地说出来:
| HTTP方法 | 对应操作 | 典型语义 | 是否携带Body |
|---|---|---|---|
| GET | 查(Read) | 获取资源列表或单个资源 | 否(规范不建议) |
| POST | 增(Create) | 创建新资源(服务端生成ID) | 是 |
| PUT | 改(Update / 全量替换) | 全量更新资源(客户端指定完整资源) | 是 |
| PATCH | 改(Update / 部分修改) | 局部更新资源(只传要改的字段) | 是 |
| DELETE | 删(Delete) | 删除指定资源 | 通常否 |
第二层:进阶原理(决定选型的核心 —— 安全 & 幂等)
这是面试官最看重的底层逻辑。你在回答选型时,必须先抛出这两个概念:
- 安全(Safe):不会修改服务器状态。只有 GET 是安全的(HEAD/OPTIONS 也是,但日常不提)。
- 幂等(Idempotent):无论执行多少次,结果都一样。
| HTTP方法 | 安全性 | 幂等性 | 核心结论(面试背下来) |
|---|---|---|---|
| GET | ✅ 安全 | ✅ 幂等 | 只查不改,放心缓存和重试 |
| DELETE | ❌ 不安全 | ✅ 幂等 | 删1次和删N次,最终状态都是“已删除”(响应可能不同,但状态一致) |
| PUT | ❌ 不安全 | ✅ 幂等 | 全量覆盖,执行N次结果相同 |
| PATCH | ❌ 不安全 | ❌ 不保证幂等(取决于实现) | 如果实现是“设置 age=18”,则是幂等的;如果是“age += 1”(自增),则非幂等 |
| POST | ❌ 不安全 | ❌ 非幂等 | 每次创建一条新数据,结果不同 |
面试话术:“选型时,我会优先从语义和幂等性出发。GET 只做查询;POST 处理非幂等的创建;PUT 用于全量覆盖;PATCH 做局部更新,但要小心业务逻辑是否幂等;DELETE 虽然是幂等的,但要做好权限和级联处理。”
第三层:实战决策树(到底怎么选?场景对照)
别再死记硬背,直接套这个业务决策逻辑:
我要拿数据,服务器状态不变? → GET
- 注意:GET 也可以传参(Query String 或路径变量),但绝对不要用 GET 传大 JSON Body(网关/代理会拒绝)。
我要新增一条数据,ID 由后端生成(如订单、报告)? → POST
- 注意:POST 非幂等,不能自动重试(否则重复下单)。
我要更新数据,且客户端知道完整的最终状态(覆盖)? → PUT
- 例如:
PUT /user/1传入完整{ name, age, address }。 - 风险:如果只传了
{ age },PUT 会把name和address置空(因为全量替换)。
- 例如:
我要更新数据,只改其中几个字段(增量更新)? → PATCH
- 例如:
PATCH /user/1只传{ age: 18 }。 - 注意:PATCH 是否幂等取决于实现。如果你传的是
{ "op": "increment", "field": "age" },那就是非幂等的。
- 例如:
我要删除某个特定资源? → DELETE
- 即使第二次删除返回 404,资源状态依然是“已删除”,所以是幂等的。
第四层:结合你的简历(实际项目怎么用)
面试官问:“你简历里的 IRMP 报告生成接口,为什么用 POST 而不是 PUT?”
你的回答(结合幂等键):
“在 IRMP 平台,
/api/report/generate是生成一份全新报告,每次生成都会产生新的报告 ID 和 PDF 文件。这是典型的 非幂等创建 操作,所以我用 POST。但为了处理网络超时导致的重复提交,我们没有依赖 HTTP 方法的幂等性,而是在请求头中增加了
Idempotent-Key(幂等键)。后端根据这个 Key 做去重,从而将非幂等的 POST 在业务层变为幂等。前端代码实现如下:javascript// 前端请求拦截器(IRMP 项目) axios.interceptors.request.use(config => { if (config.method === 'post') { // 用 uuid 生成幂等键,存在 localStorage 防止刷新丢失 let idempotentKey = localStorage.getItem('report_idempotent_key'); if (!idempotentKey) { idempotentKey = uuidv4(); localStorage.setItem('report_idempotent_key', idempotentKey); } config.headers['Idempotent-Key'] = idempotentKey; } return config; }); ```”
再补一个查询和更新的例子:
- IAMP 点云数据查询:
GET /api/pointcloud?tunnelId=xxx(查询,幂等) - WeLink 用户头像更新(全量):
PUT /api/user/avatar(传入完整图片 Base64,全量覆盖) - MMMP 告警配置修改(只改开关):
PATCH /api/alarm/config(只传{ enabled: false })
第五层:面试官的“变态追问”与你的回应
追问 1:“既然 GET 不能带 Body,那我要传很复杂的查询条件(比如多条件筛选 + 排序 + 分页)怎么办?”
“标准做法是用 Query String(查询字符串),如
GET /api/reports?page=1&size=20&status=done&sort=desc。如果条件非常复杂(超过 URL 长度限制 2048 字符),我会改用 POST 请求来查询(即POST /api/reports/search),虽然不符合 RESTful 严格规范,但在工程上这是业界通用的妥协方案(如 Elasticsearch 的_searchAPI)。”
追问 2:“我调用 DELETE,第二次返回 404,它还算幂等吗?”
“算! 幂等关注的是服务器最终状态,而不是每次的响应码。第一次删除后资源没了,第二次再删资源还是‘没了’状态,所以是幂等的。安全性和幂等性定义的是状态,而非状态码。”
追问 3:“PUT 和 PATCH 到底怎么选?后端同事让我统一用 PUT 怎么办?”
“我会坚持用 PATCH 做局部更新。因为如果用 PUT 做局部更新,前端必须把整个对象传给后端(包括没变的字段),这会导致:
- 带宽浪费(尤其是大对象)。
- 并发冲突风险:用户 A 只改了年龄,但把全量数据传回去,可能会覆盖掉用户 B 刚修改的名字(丢失更新问题)。PATCH 配合
If-Match(ETag)能更好地做并发控制。我会跟后端同事沟通,建议
PUT只用于完全替换,PATCH用于增量修改,这是 RESTful 规范明确建议的。”
面试现场组合技(最终总结)
“面试官,总结来说,我选用 HTTP 方法的核心逻辑是 ‘语义匹配 + 幂等性兜底’:
- GET:安全幂等,只查不改。
- POST:非幂等,用于新建资源。绝不自动重试,必须配合业务层的幂等键。
- PUT:幂等,用于全量覆盖。客户端必须传完整资源。
- PATCH:非严格幂等,用于局部更新。节省带宽,但要做好并发控制(版本号/ETag)。
- DELETE:幂等,删除资源。
在实际开发中,我严格按照这套规范设计接口。例如 IRMP 的报告生成(POST + 幂等键)、用户信息修改(PUT 全量 / PATCH 增量),都是这套方法论的具体落地。”