GET 请求与 POST 请求的核心区别

GET 请求与 POST 请求的核心区别(全网最全解析)

GET 和 POST 是 HTTP/1.1 规范中最常用的两种请求方法,二者核心差异体现在数据传递方式、安全性、使用场景等维度,以下是系统化对比及补充说明:

对比维度 GET 请求 POST 请求
数据传递位置 数据拼接在 URL 末尾(查询字符串,以 ? 分隔,键值对用 & 连接) 数据放在请求体(Request Body)中,URL 不可见
数据可见性 数据暴露在 URL 中,浏览器地址栏、历史记录、服务器日志均可查 数据隐藏在请求体中,相对更隐蔽(但未加密仍可抓包获取)
数据大小限制 受浏览器 / 服务器对 URL 长度的限制(如 Chrome 限制约 2KB,Tomcat 默认为 8KB) 无明确大小限制(实际受服务器配置限制,如 Tomcat 默认为 2MB,可配置)
数据类型限制 仅支持 ASCII 字符(非 ASCII 需 URL 编码) 支持任意类型数据(如二进制、JSON、表单、文件)
请求缓存 浏览器默认缓存 GET 请求(可通过 Cache-Control: no-cache 禁用) 默认不缓存(可通过响应头配置缓存)
幂等性 幂等(多次请求结果一致,如查询数据) 非幂等(多次请求可能产生副作用,如提交订单、修改数据)
安全性 低(数据暴露,易被劫持、篡改) 较高(数据不在 URL 暴露,但需配合 HTTPS 实现真正安全)
书签 / 收藏 可收藏为书签(URL 包含所有请求参数) 不可收藏(请求参数在请求体,书签仅保存 URL)
编码方式 仅支持 application/x-www-form-urlencoded 支持 application/x-www-form-urlencodedmultipart/form-data(文件上传)、application/json
浏览器刷新 / 后退 刷新 / 后退无副作用(仅重复查询) 刷新 / 后退会提示 "是否重新提交表单",易导致重复提交
历史记录 请求参数会被记录在浏览器历史记录中 请求参数不会记录在历史记录中
TCP 连接 通常一次 TCP 握手即可完成请求(HTTP/1.1 默认为持久连接) 可能分两次 TCP 握手(先发送请求头,服务器返回 100 Continue 后再发送请求体,可配置关闭)

典型使用场景

1. GET 请求
  • 数据查询(如搜索商品、分页列表、获取用户信息);
  • 传递非敏感、少量参数(如 https://example.com/search?keyword=java&page=1);
  • 静态资源请求(如加载图片、CSS、JS 文件)。
2. POST 请求
  • 提交表单(如用户注册、登录、提交订单);
  • 上传文件(如图片、文档,需指定 multipart/form-data 编码);
  • 传递敏感数据(如密码、token,需配合 HTTPS);
  • 传递大量 / 复杂数据(如 JSON 格式的请求体);
  • 执行有副作用的操作(如修改数据库、删除数据)。

代码示例(Java Servlet)

1. 处理 GET 请求
复制代码
@WebServlet("/user/query")
public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取URL中的参数
        String username = request.getParameter("username");
        String age = request.getParameter("age");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("GET请求参数:username=" + username + ", age=" + age);
    }
}
// 请求示例:http://localhost:8080/user/query?username=张三&age=20
2. 处理 POST 请求
复制代码
@WebServlet("/user/submit")
public class PostServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置请求体编码(处理中文乱码)
        request.setCharacterEncoding("utf-8");
        // 获取请求体中的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("POST请求参数:username=" + username + ", password=******");
    }
}
// 前端表单示例:
/*
<form action="/user/submit" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="提交">
</form>
*/

关键注意事项

  1. GET 请求的编码问题
    • 中文参数需手动 URL 编码(如 URLEncoder.encode("张三", "utf-8")),否则会出现乱码;
    • Tomcat 8+ 默认为 URL 编码设置为 UTF-8,低版本需配置 URIEncoding="UTF-8"
  2. POST 请求的乱码问题
    • 必须通过 request.setCharacterEncoding("utf-8") 设置请求体编码(需在获取参数前执行);
    • 响应乱码需设置 response.setContentType("text/html;charset=utf-8")
  3. 安全性误区
    • POST 并非绝对安全,抓包工具(如 Fiddler、Wireshark)可轻松获取请求体数据;
    • 敏感数据传输必须使用 HTTPS(加密请求头和请求体)。
  4. 幂等性设计
    • GET 用于 "查询",POST 用于 "提交 / 修改",遵循 RESTful 设计规范;
    • 若需实现幂等 POST(如防止重复提交),可添加唯一请求 ID(如 token)。

扩展:其他 HTTP 方法对比(补充)

方法 用途 幂等性 常用场景
PUT 更新资源(全量更新) 修改用户信息、更新订单
DELETE 删除资源 删除商品、注销账号
PATCH 更新资源(部分更新) 修改用户昵称、手机号
HEAD 仅获取响应头 检查资源是否存在

GET 和 POST 的选择核心原则:查询用 GET,提交 / 修改用 POST;敏感 / 大量数据用 POST,简单查询用 GET

相关推荐
一起养小猫25 分钟前
LeetCode100天Day6-回文数与加一
java·leetcode
程序员小假1 小时前
我们来说一下 MySQL 的慢查询日志
java·后端
独自破碎E1 小时前
Java是怎么实现跨平台的?
java·开发语言
To Be Clean Coder1 小时前
【Spring源码】从源码倒看Spring用法(二)
java·后端·spring
xdpcxq10292 小时前
风控场景下超高并发频次计算服务
java·服务器·网络
想用offer打牌2 小时前
你真的懂Thread.currentThread().interrupt()吗?
java·后端·架构
橘色的狸花猫2 小时前
简历与岗位要求相似度分析系统
java·nlp
独自破碎E2 小时前
Leetcode1438绝对值不超过限制的最长连续子数组
java·开发语言·算法
用户91743965392 小时前
Elasticsearch Percolate Query使用优化案例-从2000到500ms
java·大数据·elasticsearch
yaoxin5211233 小时前
279. Java Stream API - Stream 拼接的两种方式:concat() vs flatMap()
java·开发语言