GET 和 POST 有什么区别?
一句话回答
本质区别是语义:GET 用来获取资源,是安全且幂等的;POST 用来提交数据、创建资源,不是幂等的。"GET 有长度限制""POST 比 GET 安全"这类说法都不是协议规定:URL 长度的限制来自浏览器和服务器;在 HTTP 下两者都是明文,真正的安全要靠 HTTPS。
详细解析
语义:安全和幂等
- 安全(safe):语义上是只读的,不修改服务器上的资源。服务器顺带记日志、统计访问量不算违反
- 幂等(idempotent):同一个请求执行一次和执行多次,对服务器状态的影响相同。看的是服务器状态,不是响应:第二次 DELETE 同一个资源可能返回 404,但仍然是幂等的
| 方法 | 作用 | 安全 | 幂等 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| HEAD | 和 GET 相同,但只返回响应头 | 是 | 是 |
| OPTIONS | 查询服务器支持的方法,也用于 CORS 预检 | 是 | 是 |
| POST | 提交数据、创建资源 | 否 | 否 |
| PUT | 整体替换资源 | 否 | 是 |
| PATCH | 部分更新资源 | 否 | 不保证 |
| DELETE | 删除资源 | 否 | 是 |
常见说法辨析
- 参数位置:GET 的参数一般放在 URL 的查询字符串里,POST 的放在请求体里。这是惯例而不是限制:规范没有禁止 GET 带请求体,但没有定义它的语义,很多服务器和代理会忽略甚至拒绝;POST 的 URL 上也可以带查询参数
- 长度限制:HTTP 协议本身没有限制 URL 的长度,限制来自浏览器和服务器,URL 太长时服务器会拒绝请求,比如返回 414 URI Too Long。POST 的请求体大小同样会被服务器限制
- 缓存:GET 请求可以被缓存、可以收藏为书签,参数会随 URL 保存在浏览历史中;POST 默认都不会。刷新一个 POST 提交后的页面,浏览器会提示是否重新提交表单
- 安全性:在 HTTP 下两者都是明文,抓包都能看到。POST 只是参数不显示在地址栏里,真正的安全要靠 HTTPS(见下面的追问)
- "POST 会发两个 TCP 包":只是部分实现的行为(先发请求头、再发请求体),不是规范要求,不能一概而论
常见的 Content-Type
| Content-Type | 数据格式 | 常见场景 |
|---|---|---|
application/json |
JSON 字符串 | 前后端分离项目的接口 |
application/x-www-form-urlencoded |
name=tom&age=18,键和值都经过 URL 编码 |
HTML 表单默认的提交格式 |
multipart/form-data |
用分隔符(boundary)隔开的多个部分,可以包含二进制文件 | 文件上传 |
总结
| 对比项 | GET | POST |
|---|---|---|
| 语义 | 获取资源 | 提交数据、创建资源 |
| 安全、幂等 | 安全、幂等 | 都不是 |
| 参数位置 | 通常在 URL 查询字符串中 | 通常在请求体中 |
| 长度限制 | 受浏览器和服务器的 URL 长度限制 | 受服务器的请求体大小限制 |
| 缓存 | 默认可以缓存 | 默认不缓存 |
| 书签、浏览历史 | 参数在 URL 里,可以收藏,也会留在历史记录中 | 参数在请求体里,不会被收藏或记录 |
| 刷新页面 | 直接重新请求 | 浏览器会提示是否重新提交 |
| 传输安全 | HTTP 下是明文,要靠 HTTPS | HTTP 下同样是明文,要靠 HTTPS |
面试官可能追问
什么是幂等?为什么重要?
同一个请求执行一次和执行多次,对服务器状态的影响相同。它的意义在于重试:网络超时或连接中断时,客户端不知道请求有没有被处理,幂等的请求可以放心重试;非幂等的操作(如下单、支付)重试可能导致重复下单、重复扣款。常见做法是使用幂等键:客户端为每次操作生成一个唯一 ID,放在请求头(如 Idempotency-Key)里,重试时带同一个 ID;服务端记录处理过的 ID,遇到重复的请求直接返回第一次的结果。
POST 一定比 GET 安全吗?
不一定。在 HTTP 下两者都是明文,中间人都能看到全部内容。POST 的好处只是参数不会出现在地址栏、浏览历史和服务器访问日志里,减少了无意中泄露的机会,所以密码等敏感信息不要放在 URL 上。另外,用 GET 做修改操作更危险,一个 <img> 标签就能触发跨站请求;但 POST 也能被跨站的表单提交,同样需要 CSRF 防护(见 XSS 和 CSRF)。真正的安全要靠 HTTPS 加上鉴权和 CSRF 防护。
为什么用 POST 发送 JSON 会触发 CORS 预检?
跨域请求只有满足"简单请求"的条件才不预检:方法是 GET、HEAD、POST 之一;只使用规范允许的少数请求头;Content-Type 只能是 text/plain、application/x-www-form-urlencoded、multipart/form-data 三者之一。application/json 不在其中,所以浏览器会先发一个 OPTIONS 预检请求,服务器允许后才发送真正的请求。这和 POST 本身无关,GET 带上 Authorization 这类不在允许列表里的请求头也会触发预检。详见 跨域。
易错点
- GET 和 POST 的根本区别是语义,长度、缓存、安全性这些"区别"大多来自浏览器和服务器的实现
- 不要用 GET 做修改数据的操作:它可能被浏览器预取、被爬虫访问、被缓存,也更容易被 CSRF 利用
- PUT、DELETE 是幂等的,POST、PATCH 不保证幂等
AI 模拟面试官
用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮
这道题你掌握了吗?
选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。
学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。