GET / POST / PUT 的语义 你真的用对了吗?

2026-09-28 71 浏览 0 评论 0 字

你可能觉得 HTTP 方法(GET/POST/PUT/DELETE…)是再基础不过的东西。但恰恰是基础的东西,落地时最容易 一人一个用法 :有人用 GET 干删除、有人用 POST 传一切、有人 PUT 和 POST 一通乱用。这篇聊的是 HTTP 方法在真实开发里的语义,帮你把接口的方法和 它到底该干嘛 对齐,以及那些 看似可以、实际别扭 的常见误区。

一、为什么方法(Method)不是随便挑的

方法和语义绑定,带来的实际好处不是 规范癖 ,而是三点:

  1. 可读性 :别人看 URL 和方法,就知道这个接口是查、是增、是改、是删。 GET /user/:id vs POST /user/delete ,前者更直接。
  2. 缓存/CDN : GET 天然可缓存、可被代理、可被收藏,而 POST 通常不可缓存。给 查 的数据用 GET ,天然能借到这一层。
  3. 安全默认 :用 GET 做删除,容易被恶意链接、爬虫、误点触发(链接里带了副作用)。用安全的方法并配合鉴权,能守住底线。

二、常用方法的语义速查

方法语义典型用法幂等性
GET安全、只读查列表、查单条、查询统计幂等
POST创建 / 提交新增资源、表单提交不保证幂等
PUT覆盖更新更新整个资源幂等
PATCH局部更新只改个别字段幂等(等语义)
DELETE删除删除资源幂等

这里的 幂等 是一个关键概念: 同一个请求重复执行,结果不应该重复产生 。比如:

  • GET /user/list 重复调用,结果一样 → 幂等,安全。
  • POST /order 每调一次就新增一单 → 不幂等,所以要防止重复提交。
  • PUT /user/1 把用户数据整体覆盖成某一套 → 调几次结果一样 → 幂等。

三、最常见的两种 用反了

误区一:查询用 POST

不少开发图省事,把查询参数塞到 body 用 POST:

POST /user/list
Body: { pageNum: 1, pageSize: 10, keyword: '张三' }

问题:POST 本意是 有副作用 / 提交 ,但查询是无副作用的读。用 POST 会失去缓存、失去浏览器地址栏可分享、失去历史回退,还让 查询 和 提交 在语义上混淆。

什么时候 POST 查询合理? 查询条件特别长(接近/超出 URL 长度限制)、条件结构复杂(嵌套对象数组)、或是对外接口约定如此。这种 被迫的例外 是存在的,但 默认还是优先 GET 。

误区二:删除用 POST 或 GET 来做

GET /user/delete?id=1     // 不好:GET 带副作用
POST /user/delete         // 勉强:但语义是 删除 ,用 DELETE 更对

GET 如果做了删除,浏览器历史、站长机器人、误点链接都可能直接触发,非常危险。 用 GET 做删除 几乎是公认的坏味道。能用 DELETE 就用 DELETE,个别扣兼容的再用 POST 兜底。

四、PUT 还是 PATCH,怎么选

你看接口文档,PUT 和 PATCH 常常被 用 POST / PUT 都行 糊弄过去。但认真讲:

  • PUT:整体覆盖 。我来给你 一整套完整的含义 ,缺的字段就填空。
  • PATCH:局部更新 。我只想说 把 name 改了 ,其他字段不动。

举例 更新用户资料 :

# PUT:全量提交,我把整套资料都给你
PUT /user/1  { username, nickname, phone, email, ... }

# PATCH:只改手机号
PATCH /user/1  { "phone": "138xxxx" }

很多项目从兼容角度干脆只用 PUT,把不传的字段默认 不改 ,这种做法能跑但语义模糊。取舍建议: 如果前端每个编辑页都是 全字段回填 ,用 PUT 就够了,别硬上 PATCH;如果只是碎功能(改个状态、改个备注),用 PATCH 更恰当。

五、RESTful 风格下的 CRUD 映射

配合 RESTful,一个 用户 资源的常规映射长这样(对照真的很直观):

场景方法 + 路径说明
查列表GET /user/list分页列表
查单条GET /user/:id取一个
新增POST /user新建
更新(全)PUT /user/:id 或 PUT /user (id 在 body/front)覆盖
删除DELETE /user/:id删除

有的团队喜欢 PUT /user 把 id 放在 body 里(一件事发一个请求就搞定),有的偏好 PUT /user/:id (id 在路径)。两种都行,关键在 团队统一 ,别一个接口一种。

六、查询 vs 写操作在实际企业的常见妥协

真实项目往往没那么 规矩 ,有几个 公认的妥协 值得知道:

  1. 没有 DELETE 权限,用 POST 写删除 :很多老接口就这么做,历史原因。
  2. 查询又长又复杂,用 POST :当作 可接受的例外 。
  3. 一个接口既处理新增又处理编辑 :根据 body 里有没有 id 判断(有 id → 编辑,无 → 新增)。这种通常用 POST (语义中立),但它把 两种操作 塞一起,测试和幂等都会变复杂,能拆就拆。

这些 妥协 不是不能用,而是要知道 - 妥协的代价是前置约定、幂等、权限都要自己操心。 能严格就严格。

七、小结

HTTP 方法虽基础,但先 语义对齐 再 想当然 是写好接口的第一步:

  • 查询用 GET ,写操作用 POST/PUT/PATCH/DELETE ,别让 GET 背 删除 的锅;
  • GET 重复幂等、POST 非幂等 ,是 幂等/重复 问题(防重复提交)的根因;
  • 全量更新选 PUT ,局部改选 PATCH ,要么统一用一种、别混;
  • 路由路径 + 方法加起来才组成语义,保持团队一套 URL 风格。

下一篇,我们聊一个看似不起眼、却能造成 线上事故 的细节 - 路由注册顺序 。同样是 GET 路由,一个动态参数路由可能把其它具体接口给 吃 了。


发布评论

发布评论前请先 登录。
0 评论
点赞
收藏

评论列表 0

暂无评论