ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

【大白话说Java面试题 第217题】【10_网络协议篇】第8题:GET 和 POST 的区别

【大白话说Java面试题 第217题】【10_网络协议篇】第8题:GET 和 POST 的区别 PDF大白话说Java面试题 — 10_网络协议篇第8题GET 和 POST 的区别回答核心考点 GET 和 POST 的区别是 HTTP 面试的送分题但大厂面试官不会满足于GET 参数在 URLPOST 参数在 Body这种表层回答而是深入考察HTTP 语义RFC 7231 的规范定义、幂等性与安全性RESTful 设计的核心原则、GET 能否带 Body / POST 能否带 URL 参数协议边界的精确理解、TCP 数据包差异GET 1 个包 vs POST 2 个包的真相与例外、缓存机制浏览器缓存、代理缓存、CDN 缓存的完整链路、以及生产环境中的幂等性设计防止重复提交。面试官真正想判断的是你是否理解 GET 和 POST 的本质差异是语义而非技术实现。1. 核心区别语义是本质实现是表象RFC 7231 明确定义了 HTTP 方法的语义。GET 和 POST 的根本差异在于设计意图而非技术细节维度GETPOSTRFC 语义获取Retrieve资源提交Submit数据创建/处理资源安全性✅ 安全不修改资源状态❌ 非安全可能修改资源状态幂等性✅ 幂等多次执行效果相同❌ 非幂等多次执行效果可能不同可缓存✅ 默认可缓存❌ 默认不可缓存可手动设置参数位置URL 查询参数query string请求体Body数据可见性暴露在 URL易泄露隐藏在 Body相对安全URL 长度限制受浏览器/服务器限制通常 2~8KB无明确限制受服务器配置限制编码支持仅 ASCIIURL 编码后任意二进制支持多种 Content-Type书签/分享✅ URL 可收藏、可分享❌ 不可收藏数据在 Body浏览器行为刷新/后退无警告刷新会触发重复提交警告关键认知GET 和 POST 的区别不是参数在 URL 还是 Body而是语义上的获取 vs 提交。技术上 GET 也可以带 BodyRFC 不禁止但不推荐POST 也可以带 URL 参数常见做法但这样做违背了设计意图可能导致兼容性问题。2. 安全性与幂等性RESTful 设计的基石2.1 安全性Safe指方法是否修改服务器资源状态。GET 是安全的因为它只读取资源不修改POST 是非安全的因为它可能创建或修改资源。注意安全性 ≠ 数据传输安全。HTTP 明文传输下GET 和 POST 都不安全必须使用 HTTPS。2.2 幂等性Idempotent指多次执行相同请求服务器资源状态是否一致。这是分布式系统设计的核心概念。方法是否安全是否幂等典型副作用GET✅ 是✅ 是无HEAD✅ 是✅ 是无OPTIONS✅ 是✅ 是无PUT❌ 否✅ 是全量更新资源DELETE❌ 否✅ 是删除资源POST❌ 否❌ 否创建新资源每次创建不同资源PATCH❌ 否⚠️ 视实现部分更新资源幂等性的工程意义幂等方法可安全重试网络超时自动重发不会导致副作用幂等方法可被缓存代理和 CDN 可安全缓存响应幂等方法可被预加载浏览器预加载链接不会破坏状态。POST 的幂等性陷阱POST /orders {amount: 100} → 第一次创建订单 #1001 POST /orders {amount: 100} → 第二次创建订单 #1002非幂等解决方案使用幂等键Idempotency Key客户端生成唯一键如 UUID服务端用 Redis 缓存键 → 结果重复请求直接返回缓存结果。3. 技术实现细节3.1 GET 能否带 BodyPOST 能否不带 Body问题答案说明GET 能否带 Body✅ 可以RFC 不禁止但大多数服务器/代理/库不支持Elasticsearch 等少数场景使用POST 能否不带 Body✅ 可以如POST /logout仅触发动作无数据POST 能否带 URL 参数✅ 可以常见做法如POST /orders?sourceapp最佳实践遵循语义GET 用 URL 参数POST 用 Body避免兼容性问题。3.2 TCP 数据包差异GET 1 个包 vs POST 2 个包广为流传的说法“GET 产生 1 个 TCP 数据包POST 产生 2 个先发送 Header服务器响应 100 Continue再发送 Body”。真相GET 和 POST 的 TCP 数据包数量没有本质区别都取决于数据量和 TCP 分段POST 的 2 个包仅在启用Expect: 100-continue时出现客户端发送 Header Expect: 100-continue服务器响应100 Continue客户端发送 Body。大多数 POST 请求不启用Expect: 100-continue直接在一个 TCP 报文中发送 Header BodyGET 请求如果 URL 很长同样会被拆分为多个 TCP 报文。// 启用 Expect: 100-continue 的 POSTJavaHttpURLConnectionconn(HttpURLConnection)url.openConnection();conn.setRequestMethod(POST);conn.setRequestProperty(Expect,100-continue);// 显式启用conn.setDoOutput(true);// 此时先发送 Header等待 100 Continue 后再发送 Body3.3 缓存机制差异缓存层级GETPOST浏览器缓存✅ 默认缓存Cache-Control、ETag、Last-Modified❌ 默认不缓存代理缓存✅ 可缓存❌ 不可缓存CDN 缓存✅ 可缓存❌ 不可缓存GET 的缓存条件响应头包含Cache-Control: public或max-age无Cache-Control: no-store请求无Authorization除非响应含Cache-Control: public。POST 缓存的例外POST /search HTTP/1.1 Cache-Control: max-age3600 响应Cache-Control: public, max-age3600极少数场景下 POST 可缓存如搜索接口但需显式设置且不推荐。4. 生产环境幂等性设计实践4.1 重复提交问题用户点击提交订单后网络延迟用户再次点击导致重复扣款/重复创建订单。解决方案对比方案实现适用场景前端防抖点击后禁用按钮 N 秒简单场景不可靠F5 刷新可绕过Token 机制页面加载时获取唯一 Token提交时校验表单提交幂等键Idempotency Key客户端生成 UUID服务端 Redis 缓存结果API 接口、分布式系统数据库唯一索引订单号唯一重复插入报错最终一致性兜底幂等键最佳实践// 客户端StringidempotencyKeyUUID.randomUUID().toString();headers.set(X-Idempotency-Key,idempotencyKey);// 服务端PostMapping(/orders)publicResponseEntity?createOrder(RequestHeader(X-Idempotency-Key)Stringkey,RequestBodyOrderRequestrequest){// 1. 检查 Redis 是否已处理StringcachedResultredisTemplate.opsForValue().get(idempotency:key);if(cachedResult!null){returnResponseEntity.ok(cachedResult);// 直接返回缓存结果}// 2. 执行业务逻辑OrderorderorderService.create(request);// 3. 缓存结果设置过期时间如 24 小时redisTemplate.opsForValue().set(idempotency:key,JsonUtils.toJson(order),Duration.ofHours(24));returnResponseEntity.ok(order);}4.2 GET 误用的安全隐患误用场景风险正确做法GET /delete?id123浏览器预加载、爬虫误触发删除改用DELETE /resources/123GET /transfer?toxxxamount100URL 参数泄露CSRF 攻击改用POST CSRF Token敏感信息放 URL浏览器历史、服务器日志、Referer 泄露改用POST Body5. 常见误区澄清误区正确理解“POST 比 GET 更安全”HTTP 下两者都不安全HTTPS 下两者都安全。POST 的 Body 虽不在 URL但仍可被中间人窃听无 HTTPS 时“GET 只能传 ASCIIPOST 可以传二进制”是 URL 编码的限制不是 GET 本身的限制。GET 用 Base64 编码同样可以传二进制“GET 有长度限制POST 没有”HTTP 协议本身无限制限制来自浏览器URL 长度和服务器配置Body 大小“GET 用于获取POST 用于提交”这是语义规范不是技术强制。技术上 GET 可以提交POST 可以获取但违背规范“POST 产生 2 个 TCP 包”仅在Expect: 100-continue时成立默认情况下 POST 和 GET 一样都是 1 个包6. 面试官追问与高分回答模板追问 1“GET 和 POST 的区别是什么”低分回答“GET 参数在 URLPOST 参数在 BodyGET 有长度限制POST 没有GET 不安全POST 安全。”全是表象没有触及语义高分回答GET 和 POST 的本质区别是语义GET 用于获取资源POST 用于提交数据创建/处理资源。这个语义差异衍生出五个关键区别安全性GET 是安全的不修改资源状态POST 是非安全的可能修改状态幂等性GET 是幂等的多次执行效果相同POST 是非幂等的多次执行可能创建多个资源缓存GET 默认可缓存POST 默认不可缓存参数位置GET 参数在 URL受长度限制、易泄露POST 参数在 Body支持更大数据、更多编码类型浏览器行为GET 可书签、可后退刷新POST 刷新会触发重复提交警告。注意HTTP 协议本身不限制 GET 带 Body 或 POST 带 URL 参数但违背语义会导致兼容性问题。追问 2“GET 是幂等的POST 不是幂等的这是什么意思”低分回答“GET 执行多次结果一样POST 执行多次结果不一样。”没有解释副作用高分回答幂等性是指多次执行相同请求服务器资源状态是否一致不是指返回结果是否相同。GET 是幂等的无论调用 1 次还是 100 次服务器资源状态不变只读取。即使返回结果不同如GET /news返回最新新闻也是幂等的因为资源本身未被修改。POST 是非幂等的POST /orders每次调用都会创建一个新订单资源状态改变。如果网络超时后自动重试可能导致重复创建。幂等性的工程价值幂等方法可安全重试、可缓存、可预加载。POST 的非幂等性要求我们在分布式系统中设计幂等键等机制防止重复提交。追问 3“GET 请求能带 Body 吗POST 请求能不带 Body 吗”高分回答技术上都可以但违背语义规范GET 带 BodyRFC 7231 不禁止但大多数服务器、代理、库不支持。Elasticsearch 等少数场景使用 GET Body 传递复杂查询条件。POST 不带 Body完全可以如POST /logout仅触发登出动作无需数据。POST 带 URL 参数常见做法如POST /orders?sourceapp标识来源。最佳实践是遵循语义GET 用 URL 参数POST 用 Body。追问 4“POST 产生 2 个 TCP 数据包GET 产生 1 个这个说法对吗”高分回答“这个说法不完全正确。GET 和 POST 的 TCP 数据包数量没有本质区别都取决于数据量和 TCP 分段。POST 产生 2 个包的情况仅在启用Expect: 100-continue时出现客户端先发送 Header服务器响应100 Continue客户端再发送 Body。但大多数 POST 请求不启用这个机制直接在一个 TCP 报文中发送 Header Body。反过来GET 的 URL 如果很长如大量查询参数同样会被拆分为多个 TCP 报文。所以’POST 2 个包、GET 1 个包’是特定条件下的现象不是普遍规律。”追问 5“如何防止 POST 请求的重复提交”高分回答防止 POST 重复提交需要多层防御前端层按钮防抖点击后禁用 N 秒但不可靠F5 刷新可绕过Token 层页面加载时获取唯一 Token提交时校验Token 只能使用一次幂等键层客户端生成 UUID 作为X-Idempotency-Key服务端用 Redis 缓存’键 → 结果’重复请求直接返回缓存数据库层唯一索引兜底如订单号唯一重复插入报错。推荐组合前端防抖 幂等键 数据库唯一索引三层防御确保万无一失。追问 6“什么情况下 GET 和 POST 都不安全HTTPS 能完全解决吗”高分回答HTTP 协议下GET 和 POST 都是明文传输都不安全。GET 的参数在 URL 中更容易通过浏览器历史、服务器日志、Referer 泄露POST 的参数在 Body 中相对隐蔽但无 HTTPS 时仍可被中间人窃听。HTTPS 能解决传输层的安全问题加密、完整性、认证但无法解决应用层漏洞如 SQL 注入、XSS与 GET/POST 无关服务器被入侵HTTPS 只保证’与真实服务器通信’不保证’服务器是诚实的’敏感信息放 URL即使 HTTPSURL 参数仍可能出现在服务器日志、浏览器历史中。所以敏感操作如支付、密码修改必须用 POST HTTPS且敏感数据绝不放 URL。7. 方案选型速查表场景推荐方法核心理由获取资源/查询数据GET安全、幂等、可缓存创建新资源POST非幂等每次创建不同资源全量更新资源PUT幂等多次更新结果一致部分更新资源PATCH视实现是否幂等删除资源DELETE幂等删除已删除资源无影响提交表单登录、注册POST非安全、数据在 Body文件上传POST multipart/form-data支持二进制大文件复杂查询条件POST JSON Body条件复杂URL 无法表达触发动作发送邮件、导出POST非安全、有副作用面试官想要的满分总结GET 和 POST 的区别不是参数在 URL 还是 Body而是语义上的获取 vs 提交。这个语义差异是 RFC 7231 的规范定义衍生出安全性、幂等性、缓存、浏览器行为等一系列技术差异。安全性指是否修改资源状态GET 安全POST 非安全幂等性指多次执行效果是否一致GET 幂等POST 非幂等。这两个属性是 RESTful API 设计的基石决定了方法能否被缓存、能否被安全重试。技术细节上GET 可以带 Body不推荐POST 可以不带 Body完全可以POST 产生 2 个 TCP 包仅在Expect: 100-continue时成立。HTTP 协议本身对 URL 长度和 Body 大小没有限制限制来自浏览器和服务器配置。生产环境中POST 的非幂等性是最大的工程挑战。必须通过幂等键Idempotency KeyRedis 缓存数据库唯一索引多层防御防止网络超时重试导致的重复提交。同时绝对禁止用 GET 执行删除/转账等敏感操作避免浏览器预加载和 CSRF 攻击。最后记住GET 和 POST 的选择首先看语义其次看技术约束。语义对了技术细节自然对语义错了技术再完美也是错的。觉得对您有帮助麻烦点点关注啦您的关注是我创作的最大动力~
返回列表