(一)引子
我们知道http是无状态协议,这意味着同一个浏览器发出的前后两次请求之间没有任何联系,请求得到响应之后这次连接就断开了,下一次发出的请求是全新的。
但是大部分业务不可能通过一次请求就能搞定,需要分好几个步骤(也就是发好几次请求),这些步骤在逻辑上必须要关联起来不能分开。比如某人在淘宝买东西,往购物车加一件东西就需要发一次请求,但是这些东西必须放到同一个人的购物车中,那么如何识别这些请求到底是不是来自同一人呢?如果没法识别,那么多人逛淘宝,我刚看中一件商品,结果加到别人的购物车中了,淘宝还不乱套了?
但是现在淘宝活的很滋润,说明必然有某种技术是可以识别请求到底是来自谁的,这就是cookie机制。这玩意儿的运作原理大概是这样:每次发请求的时候,在请求头加入一个cookie属性,长的一般都是下面这样子
Cookie: JSESSIONID=B62233B5E2AA568E02C7E10332EA56E9
这个等号后面的值就相当于一个身份证,用来识别请求来自哪里。同一个浏览器向同一个网站发出的请求都会使用同一个身份证,这样服务器就可以把拥有同一个身份证的请求视为同一个人的操作。这也就是所谓的会话(session)管理,将连续的请求在逻辑上关联起来,像一次会话,有上下文的联系。
(二)客户端(浏览器)的cookie管理
上面说,同一个浏览器向同一个网站发出的请求会拥有同一个sessionId(不管是这个浏览器打开多个窗口还是多个标签页),但是访问另一个网站的时候就不能再使用同一个sessionId;而同一台电脑不同的浏览器访问同一个网站时,使用的也是另一个sessionId。
这说明,每个浏览器都有自己的一套cookie管理机制;而同一个浏览器对每个不同的网站的sessionId也有一套机制。详细可以参考这里:http://hovertree.com/h/bjaf/tll89y8p.htm
(三)服务器端的身份识别
那么带着cookie的请求到达服务器之后又是如何被处理的呢?由于我个人比较熟悉Java,所以就以Servlet和Tomcat为例说明。
请求(默认8080端口)到达服务器后会被tomcat拦截,并将其封装成一个HttpServletRequest对象,然后将这个对象
的引用传递给相应的Servlet进行处理。
HttpServletRequest的API中有个getSession()方法,用来获取与该请求相关的Session对象。这说明,Tomcat在把请
求封装成HttpServletRequest对象的时候,其实已经提取过其cookie属性中的sessionId值了,然后根据这个值去寻找
跟它关联的Session对象,并将其引用赋值给HttpServletRequest实现类中的某个private属性。
这里要注意的是,第一次请求到来的时候,sessionId应该是空的,因而也就不存在与其关联的Session对象。实际上
,正常流程是,第一次请求的时候,服务器端的Servlet代码内调用了以下代码:
request.getSession();
有了这句代码,Tomcat才会建立一个Session对象,并为其生成一个Id值,同时在(给这个第一次请求的)响应中的
Header部分,加入一个指令“set-cookie: jsessionid=XXXX” ,这里的XXXX就是在服务器生成的sessionId。有了这个
指令,浏览器才会为这个网站建立cookie。也就是说,浏览器不会主动为某个网站建立cookie,cookie或Session的建
立是由服务器端主动发起的,SessionId也是服务器生成的。
那么第二次及以后再调用request.getSession();的时候,就可以找到与之关联的Session对象了,然后我们就可以把
request中的数据存放到这个Session对象中,这样就实现了会话。