GET 和 POST 有什么区别?
简化版
最核心的区别:GET 用来「获取」资源、参数放在 URL 里,POST 用来「提交」数据、参数放在请求体里。GET 是安全(不改服务器状态)且幂等的,会被浏览器缓存、能被收藏和放进历史;POST 不安全不幂等,不会被缓存。至于「POST 比 GET 安全」是个误区——不用 HTTPS 的话两者都是明文。
详细版
| 维度 | GET | POST |
|---|---|---|
| 语义 | 获取资源 | 提交数据 |
| 参数位置 | URL 查询字符串 ?a=1&b=2 | 请求体(body) |
| 长度限制 | 受浏览器/服务器 URL 长度限制 | 无协议限制(受服务器配置) |
| 缓存 | 可被缓存 | 默认不缓存 |
| 收藏/历史 | 可收藏、进浏览器历史 | 不可 |
| 幂等/安全 | 安全 + 幂等 | 都不是 |
| 后退/刷新 | 无害 | 会提示「重新提交表单」 |
| 编码 | 只 application/x-www-form-urlencoded | 多种(含 multipart/form-data 传文件) |
- GET 把参数拼在 URL 上,适合「查询」这类不改变服务器数据的操作。
- POST 把数据放在请求体,适合「新增、提交表单、上传文件」这类会改变服务器状态的操作。
完整版教学
一、区别的根源:语义不同
GET 和 POST 的所有差异,本质来自 HTTP 给它们规定的语义:GET 表示「读取」,POST 表示「写入/提交」。其他区别都是围绕这个语义的合理设计:
- 因为 GET 是「读」,天然安全(不改数据)、幂等(读多少次结果一样),所以可以放心缓存、收藏、放进历史、被预取;
- 因为 POST 是「写」,会改变服务器状态,所以不能缓存(否则拿到旧结果就错了)、刷新会提示「重新提交」(防止重复下单)。
理解「GET 读、POST 写」这个语义差异,其余的表格内容都能推出来。
二、参数放 URL vs 放 body
- GET 参数在 URL 的查询字符串里(
?key=value),所以会显示在地址栏、被浏览器历史和服务器日志记录,也因此有长度限制(URL 长度受浏览器和服务器限制,HTTP 协议本身没规定)。 - POST 参数在请求体里,不显示在 URL,长度没有协议级限制(能传大数据、文件)。
所以传敏感信息、大数据、文件用 POST;传查询条件用 GET。
三、破除「POST 比 GET 安全」的误区
很多人以为 POST 比 GET 安全,这是错的:
- 不用 HTTPS 时,GET 和 POST 都是明文传输,抓包都能看到。POST 的 body 一样能被截获。
- POST 只是「参数不在 URL 上」,所以不会出现在地址栏、浏览器历史、服务器访问日志、referer里——这只是降低了泄露面,不等于「加密」或「安全」。
- 真正的安全靠 HTTPS(加密传输),和用 GET 还是 POST 无关。
记住:「安全」在 HTTP 语境里指「不改变服务器状态(safe method)」,不是「加密防窃听」。 别把两个「安全」搞混。
四、幂等性:GET 幂等,POST 不幂等
- GET 幂等:查询一次和查询多次,服务器状态不变、结果一致。
- POST 不幂等:提交两次可能创建两条记录(重复下单)。这就是为什么刷新一个 POST 页面浏览器会警告「确认重新提交表单」——防止你不小心付两次款。
幂等性是接口设计的重要概念(详见「HTTP 请求方法与幂等性」那道题),也是为什么「提交订单」这类操作要做防重(如幂等 token)。
五、一个技术细节:GET 也能带 body 吗
严格说 HTTP 协议不禁止 GET 带请求体,但语义上不推荐、很多服务器和代理会忽略 GET 的 body。所以实践中「GET 参数放 URL、POST 参数放 body」是约定俗成的规范,别写「带 body 的 GET」。
六、常见误区
- ❌ 以为 POST 比 GET 安全——不加密时都是明文,POST 只是参数不暴露在 URL。
- ❌ 以为 GET 长度限制是 HTTP 规定的——是浏览器/服务器对 URL 长度的限制,协议没规定。
- ❌ 用 GET 做「增删改」——GET 应当是安全幂等的「读」,改数据用 POST/PUT/DELETE。
- ❌ 以为 POST 一定不幂等就不用管——重复提交要靠幂等设计(token)防重。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| GET | 语义是获取资源,通常参数在 URL,安全且幂等 |
| POST | 语义是提交处理,body 承载数据,通常非幂等 |
| 安全性 | 是否加密取决于 HTTPS,不取决于方法 |
GET /users?id=1
POST /orders
body: {"sku":"A","count":1}
GET 和 POST 的核心区别是语义,不是“一个能传参数、一个不能”。
- 误区:POST 比 GET 更安全。 HTTP 下二者都是明文,HTTPS 下二者都会被加密;URL 可能被日志记录是另一个问题。
- 误区:GET 不能带 body。 协议层没有绝对禁止,但语义和兼容性差,工程上不建议依赖 GET body。
- 误区:POST 一定不能被缓存。 POST 默认不常缓存,但满足明确缓存头时也可被缓存,关键看语义和缓存策略。
- 追问:GET 为什么幂等? 重复获取同一资源不应改变服务器状态,结果语义上等价。
- 追问:URL 长度限制来自哪里? HTTP 规范不是核心限制,主要来自浏览器、服务器和代理实现。
- 追问:创建订单为什么不用 GET? 创建订单会改变服务器状态且可能重复产生副作用,应使用 POST 等非安全方法。
七、加强记忆
GET「读」、参数在 URL、安全幂等、可缓存可收藏;POST「写」、参数在 body、不安全不幂等、不缓存。区别根源是语义(读 vs 写)。「POST 更安全」是误区——不加密时都明文,真安全靠 HTTPS;这里的「安全」指不改服务器状态,不是防窃听。