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-urlencoded、multipart/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>
*/
关键注意事项
- GET 请求的编码问题 :
- 中文参数需手动 URL 编码(如
URLEncoder.encode("张三", "utf-8")),否则会出现乱码; - Tomcat 8+ 默认为 URL 编码设置为 UTF-8,低版本需配置
URIEncoding="UTF-8"。
- 中文参数需手动 URL 编码(如
- POST 请求的乱码问题 :
- 必须通过
request.setCharacterEncoding("utf-8")设置请求体编码(需在获取参数前执行); - 响应乱码需设置
response.setContentType("text/html;charset=utf-8")。
- 必须通过
- 安全性误区 :
- POST 并非绝对安全,抓包工具(如 Fiddler、Wireshark)可轻松获取请求体数据;
- 敏感数据传输必须使用 HTTPS(加密请求头和请求体)。
- 幂等性设计 :
- GET 用于 "查询",POST 用于 "提交 / 修改",遵循 RESTful 设计规范;
- 若需实现幂等 POST(如防止重复提交),可添加唯一请求 ID(如 token)。
扩展:其他 HTTP 方法对比(补充)
| 方法 | 用途 | 幂等性 | 常用场景 |
|---|---|---|---|
| PUT | 更新资源(全量更新) | 是 | 修改用户信息、更新订单 |
| DELETE | 删除资源 | 是 | 删除商品、注销账号 |
| PATCH | 更新资源(部分更新) | 是 | 修改用户昵称、手机号 |
| HEAD | 仅获取响应头 | 是 | 检查资源是否存在 |
GET 和 POST 的选择核心原则:查询用 GET,提交 / 修改用 POST;敏感 / 大量数据用 POST,简单查询用 GET。