在面试或者笔试时,经常会被问到 HTTP 方法中 get 和 post 的异同点。本文简单整理归纳了一下,以备忘。
1、"get/post" VS "web 中的 get/post"
一些 web 相关职位的面试,无论有没有提 web,面试中的 get/post,一般就是指 web 中的 get/post。需要注意的是,web 中的 get/post 只是 http 中的 get/post 的子集,所以如果谈 get 与 post 的区别,要是面试官有心挖坑,就要特别注意下你们聊的是不是 web 中的 get/post。(本文接下去讲的 get/post 基本上是基于 web 的)
关于 get/post,可以查看 rfc-2616 了解详情:
- get: RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1
- post: RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1
其实,http 中的 get 与 post 只是单纯的名字上的区别,get 请求的数据也可以放在 request body 中,只是浏览器没有实现它,但是 get 并不只是在 web 中使用。所以,说到 get/post 的区别,会直接条件反射地去说 web 中的 get/post 区别。而 web 中 get 以及 post,其实都可以往服务端发送数据,get 是将数据拼接在 url 上(有必要时需要 encode),而 post 是将数据封装在 request body 中,发送过去。
get/post 可以顾名思义地理解,get 是用来请求数据,那么,既然是请求数据,为什么还要带上数据呢?其实很好理解,比如一个新闻页面,有很多内页,那么 get 请求可能带上的类似这样的参数 page=1
,即为请求第一页的数据。post 的话顾名思义就是发送数据,所以需要带上数据。
2、get 请求是安全和幂等的
何谓安全?这里的安全指的是在规范的定义下,get 操作不会修改服务器的数据,无论做多少次 get 请求,服务端的数据都是不会有变化的,所以说 get 请求是安全的。"get 请求是安全的" 换句话说就是 "get 请求不产生副作用",它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。
何谓幂等?幂等是说,同一个请求原封不动的发送 N 次和 M 次(N 不等于 M,N 和 M 都大于 1),服务器上资源的状态最终是一致的,相应地服务器返回的内容也是一致的。get 请求是幂等的,因为无论请求多少次,服务器上的资源状态不变,而 post 则不然,post 会更新服务器的数据。比如发贴是非幂等的,重复 10 次发贴请求会创建 10 个帖子。但修改帖子内容是幂等的,一个修改请求重复无论多少次,帖子最终状态都是一致的。
关于幂等再举个数学上的例子。对于单目运算,如果一个运算对于在范围内的所有的一个数多次进行该运算所得的结果和进行一次该运算所得的结果是一样的,那么我们就称该运算是幂等的。比如绝对值运算就是一个例子,在实数集中,有 abs(a)=abs(abs(a))
。这个例子非常的好,abs(a) 可以表示做了一次 get 请求后的服务器上的资源状态,对其继续做 abs 运算,状态不变,这就好比做了一次 get 请求,继续再做,而该资源状态一直不变,所以请求得到的东西也就不会变。
因此,按照某一 ID 阅览文章就是安全而幂等的,应当使用 get。而注册用户、登录等操作会改变服务器的资源状态,不是安全而幂等的,应当使用 post。
3、post 相对 get 请求是 "安全" 的
这里的 "安全",和第二点所讲的 "安全" 又是两回事了。这里的 "安全" 是密码学上的,也就是大多数场景中 "安全" 的意思。
其实该点颇有点(post)五十步笑(get)百步之嫌。
我们知道,get 请求是将数据附在 url 上,而 post 是将数据封装在 request body 中。所以 get 请求附加的参数可能会被人在浏览器地址栏上直接看到,或者查看一下浏览器的历史记录或者日志,就能看到你的参数。而 post 因为不能被缓存,也不能被保存为书签,所以请求过了就没有记录了?请求参数就不能被截获了?非也,抓个包就可以看到了。
所以,post 请求只是相对安全的。(防君子防不了小人)
4、get 请求发送数据更小
http 协议中的 get/post 并没有发送数据大小的限制,对发送数据大小产生限制的是浏览器以及操作系统、服务器,http 本身并没有对 url 长度有所限制。
IE 对 URL 长度的限制是 2083字节(<=IE 8)。对于其他浏览器,如 Netscape、FireFox 等,理论上没有长度限制,其限制取决于操作系统以及服务器的支持。而 chrome 遇到长度很长的 URL 时,会直接 崩溃。
URL 长了,对服务器处理也是一种负担。原本一个会话就没有多少数据,现在如果有人恶意地构造几个几 M 大小的 URL,并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是,把告诉服务器 Content-Length 是一个很大的数,然后只给服务器发一点儿数据,嘿嘿,服务器你就傻等着去吧。哪怕你有超时设置,这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给 URL 长度加限制。
理论上讲,POST 是没有大小限制的,HTTP 协议规范也没有进行大小限制,说 "POST数据量存在80K/100K 的大小限制" 是不准确的,POST 数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。
5、get 能被缓存,post 不能被缓存
这点非常容易理解,打开一个页面,如果之前打开过,那么很明显速度会加快,这是因为 html/js/css/img 等文件都能被浏览器缓存(也可以被服务器缓存),而这些文件的获取,都是用的 get 请求。事实上,web 中的绝大多数请求都是用 get 完成的,post 请求目前为止我只是在 ajax 以及 form 表单中有见过。
但是实际上,http 协议中 post 和 get 都是可以被缓存的,不过不要惊讶,浏览器的实现总是比标准厉害。(post 和 get 真的只有名字上的区别啊。。)
因为 get 请求会有缓存,所以在开发过程中,很多时候我们要手动清除缓存,不然看不到修改后的样子。
关于 get 请求能被缓存我有个惨痛的经历。在一次开发中,要做一个跳转页面(假设为 a.index,同时需要在主页面(假设为 index.htm)中带个参数(假设为 tmp)过去,为了方便,直接将参数附加在了跳转页面的 url 上,页面地址为 a.htm?tmp,直接取其 location.search 属性即可获取参数。之后修改了 a.htm 页面的内容,但是发现一直不生效,并且已经清除了 a.htm 页面的缓存,排查了很久,原因很显然,缓存地址为 a.htm?tmp,需要清除该地址的缓存!
所以一般要获取最新的文件(非缓存文件),可以加个类似时间戳一样的参数。
6、form 表单可以用 get 提交
form 表单有个 method 属性,一般为 "post"。但是,其实 method 属性是可以为 "get" 的,甚至,默认就是 "get"。
如果是 "post" 方式,数据藏在 request body 中,如果是 "get" 方式,数据拼接在 url 上。但是,一般 form 表示都与 "数据提交" 相辅相成,会对服务端数据做修改,所以一般都是以 "post" 的方式。
7、求他:put 以及 delete
说完 get/post,再来简单谈谈他们的其他几个好基友吧。
Http 定义了与服务器交互的不同方法,最基本的方法有 4 种,分别是 GET,POST,PUT,DELETE。URL 全称是资源描述符,我们可以这样认为:一个 URL 地址,它用于描述一个网络上的资源,而 HTTP 中的 GET,POST,PUT,DELETE 就对应着对这个资源的查,改,增,删 4 个操作。
- GET:无副作用,幂等,不可带 Request Body
- PUT:副作用,幂等,可以带 Request Body
- POST:副作用,非幂等,可以带 Request Body
- DELETE:副作用,幂等,不可带 Request Body
get 和 post 成功之后应该返回 200;而 put 和 delete 在成功时则推荐使用 202.
8、Read More
- 浅谈HTTP中Get与Post的区别
- GET和POST有什么区别?及为什么网上的多数答案都是错的。
- 详解HTTP中GET和POST的区别
- 从HTTP GET和POST的区别说起
- post 和get请求的区别(html)?
- GET vs. POST
随机推荐
-
CSS3 Gradient 渐变
转载自:http://www.w3cplus.com/content/css3-gradient CSS3发布很久了,现在在国外的一些页面上常能看到他的身影,这让我羡慕已久,只可惜在国内为了兼容IE, ...
-
Jsp字符编码过滤器
通过此过滤器,可以实现统一将编码设置为UTF-8. 1.首先在web.xml中配置,添加如下代码: <!-- 过滤器 --> <filter> <filter-name& ...
-
大型网站系统架构实践(五)深入探讨web应用高可用方案
从上篇文章到这篇文章,中间用了一段时间准备,主要是想把东西讲透,同时希望大家给与一些批评和建议,这样我才能有所进步,也希望喜欢我文章的朋友,给个赞,这样我才能更有激情,呵呵. 由于本篇要写的内容有点多 ...
-
(spring-第5回【IoC基础篇】)spring容器从加载配置文件到实例化bean的内部工作机制
前面讲过,spring的生命周期为:实例化前奏-->实例化-->实例化后期-->初始化前期-->初始化-->初始化后期-->bean的具体调用-->销毁前-- ...
-
jquery获取浏览器高度、宽度和滚动条高度(来自网络)
Jquery代码: alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(document).height()); //浏览器时下窗口文档的高度 ale ...
-
Nodejs前端服务器压缩图片
Nodejs作为前端服务器,自然能承担处理图片的能力, 使用GM for nodejs 作为图片处理器,调用ImageMagick处理图片 使用ImageMagick var imageMagick ...
-
升级CentOS5.6_X64 python2.4.3到2.7
本文转自:http://hxl2009.blog.51cto.com/779549/1031310 升级CentOS 5.6 64位版python到2.7.31. 背景CentOS 5.6自带的Pyt ...
-
正则表达式在Java中的使用
目录 介绍 从简单例子认识正则表达式匹配 Java中对正则表达式的支持(各种语言有相应的实现) 初步认识 . + * ? 范围 认识\s \w \d - 下面介绍数字和字母的正则表达, 这是编程中使用 ...
-
workerman与thinkphp结合
运行workerman需要安装pcntl和event或者libevent pcntl安装方法: 以php-5.5.20为例,实际情况按自己安装的PHP目录 一. 找到PHP源码,进入 php-5.5. ...
-
synchronized(){}同步代码块笔记(新手笔记,欢迎纠正)
/* 内容:同步代码块,目的是解决多线程中的安全问题.什么安全问题呢??就是在执行run方法时,假如线程-0刚刚获得执行权, *还没执行时,就挂那了,这时线程-1获得执行权,并进行执行,就有可能出现负 ...