GET 与 POST 的区别

从语义、缓存、数据长度、安全性对比 GET 和 POST 请求

问题

GET 与 POST 有什么区别?从语义、缓存、数据长度、安全性等方面说明。

解答

语义区别

  • GET:获取资源,是幂等的(多次请求结果相同)
  • POST:提交数据,可能产生副作用(如创建资源)
// GET - 获取用户列表
fetch('/api/users?page=1&limit=10')

// POST - 创建新用户
fetch('/api/users', {
  method: 'POST',
  body: JSON.stringify({ name: 'John' })
})

缓存

  • GET:可被浏览器缓存,可被 CDN 缓存,会保存在浏览器历史记录中
  • POST:默认不缓存
// GET 请求可以通过 URL 直接访问缓存
// 浏览器会根据 Cache-Control、ETag 等头部决定是否使用缓存

// POST 请求需要手动设置才能缓存
fetch('/api/data', {
  method: 'POST',
  headers: {
    'Cache-Control': 'max-age=3600' // 通常服务端不会这样做
  }
})

数据传输

  • GET:参数在 URL 中,受 URL 长度限制(浏览器通常限制 2KB-8KB)
  • POST:参数在请求体中,理论上无大小限制(服务器可能有限制)
// GET - 参数拼接在 URL
fetch('/api/search?keyword=javascript&category=frontend')

// POST - 参数在 body 中,可传输大量数据
fetch('/api/upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    content: '大量数据...',
    files: [/* 文件数据 */]
  })
})

安全性

两者在传输层面安全性相同(都需要 HTTPS 加密),区别在于:

  • GET:参数暴露在 URL 中,会被浏览器历史、服务器日志记录
  • POST:参数在请求体中,相对不易泄露
// 不安全 - 密码暴露在 URL 中
fetch('/api/login?username=admin&password=123456')

// 相对安全 - 密码在请求体中
fetch('/api/login', {
  method: 'POST',
  body: JSON.stringify({
    username: 'admin',
    password: '123456'
  })
})

对比表格

特性GETPOST
语义获取资源提交数据
幂等性幂等非幂等
缓存可缓存默认不缓存
数据位置URL 参数请求体
数据大小受 URL 长度限制理论无限制
回退/刷新无害数据会重新提交
书签可收藏不可收藏

关键点

  • GET 用于获取数据,POST 用于提交数据,这是最本质的语义区别
  • GET 请求可被缓存、收藏、保存在历史记录中,POST 不行
  • GET 参数在 URL 中有长度限制,POST 在请求体中无此限制
  • 两者传输安全性相同,但 GET 参数更容易被记录和泄露
  • 选择依据:查询用 GET,修改用 POST,敏感数据用 POST