《Java中设置session的详细解释》由会员分享,可在线阅读,更多相关《Java中设置session的详细解释(9页珍藏版)》请在金锄头文库上搜索。
1、Java 中设置 session 的详细解释一、术语 session 在我的经验里,session 这个词被滥用的程度大概仅次于 transaction,更加有趣的是transaction 和 session 在某些语境下的含义是相同的。session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/ 消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程能称之为一个 session。有时候我们能看到这样的话“在一个浏览器会话期间, .”,这里的会话一词用的就是其本义,是指从一个浏览器窗口打开到关闭这个期间。最混乱的是“用户(客户端)在一次会话期间”这样一句话,他可能指用户的一
2、系列动作(一般情况下是同某个具体目的相关的一系列动作,比如从登录到选购商品到结账登出这样一个网上购物的过程,有时候也被称为一个transaction) ,然而有时候也可能仅仅是指一次连接,也有可能是指含义,其中的差别只能靠上下文来推断。然而当 session 一词和网络协议相关联时,他又往往隐含了“面向连接”和/或“保持状态”这样两个含义, “面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到对方接了电话通信才能开始,和此相对的是写信,在你把信发出去的时候你并不能确认对方的地址是否正确,通信渠道不一定能建立,但对发信人来说,通信已开始了。“保持状态” 则是指通信的一方
3、能够把一系列的消息关联起来,使得消息之间能互相依赖,比如一个服务员能够认出再次光临的老顾客并且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个 TCP session”或“ 一个 POP3 session”。而到了 web 服务器蓬勃发展的时代,session 在 web 研发语境下的语义又有了新的扩展,他的含义是指一类用来在客户端和服务器之间保持状态的解决方案。有时候session 也用来指这种解决方案的存储结构,如“把 xxx 保存在 session 里”。由于各种用于 web 研发的语言在一定程度上都提供了对这种解决方案的支持,所以在某种特定语言的语境下,session 也被用来指代
4、该语言的解决方案,比如经常把 Java 里提供的javax.servlet.http.HttpSession 简称为 session。鉴于这种混乱已不可改动,本文中 session 一词的运用也会根据上下文有不同的含义,请大家注意分辨。在本文中,使用中文“浏览器会话期间 ”来表达含义 ,使用“session 机制” 来表达含义,使用“session”表达含义,使用具体的“HttpSession”来表达含义二、HTTP 协议和状态保持HTTP 协议本身是无状态的,这和 HTTP 协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为
5、,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或一个普通的(非会员制)大卖场之间的关系相同。然而聪明(或贪心?)的人们非常快发现如果能够提供一些按需生成的动态信息会使web 变得更加有用,就像给有线电视加上点播功能相同。这种需求一方面迫使 HTML 逐步添加了表单、脚本、DOM 等客户端行为,另一方面在服务器端则出现了 CGI 规范以响应客户端的动态请求,作为传输载体的 HTTP 协议也添加了文件上载、cookie 这些特性。其中 cookie 的作用就是为了解决 HTTP 协议无状态的缺陷所作出的努力。至于后来出现的session 机制则是又一种在客户端和服务器之间保持状态的解决方
6、案。让我们用几个例子来描述一下 cookie 和 session 机制之间的差别和联系。笔者原来常去的一家咖啡店有喝 5 杯咖啡免费赠一杯咖啡的优惠,然而一次性消费 5 杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:1、该店的店员非常厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。2、发给顾客一张卡片,上面记录着消费的数量,一般更有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会和以前或以后的消费相联系起来。这种做法就是在客户端保持状态。3、发给顾客一张会员卡,除了卡
7、号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。由于 HTTP 协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说 cookie 机制采用的是在客户端保持状态的方案,而 session 机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以 session 机制可能需要借助于cookie 机制来达到保存标识的目的,但实际上他更有其他选择。三、理解 cookie 机制 cookie 机
8、制的基本原理就如上面的例子相同简单,不过更有几个问题需要解决:“会员卡”怎么分发;“会员卡” 的内容;及客户怎么使用“ 会员卡” 。正统的 cookie 分发是通过扩展 HTTP 协议来实现的,服务器通过在 HTTP 的响应头中加上一行特别的指示以提示浏览器按照指示生成相应的 cookie。然而纯粹的客户端脚本如 JavaScript 或 VBScript 也能生成 cookie。而 cookie 的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的 cookie,如果某个 cookie 所声明的作用范围大于等于将要请求的资源所在的位置,则把该 cookie 附在请求资
9、源的 HTTP 请求头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示,如果某家分店还发行了自己的会员卡,那么进这家店的时候除了要出示麦当劳的会员卡,还要出示这家店的会员卡。cookie 的内容主要包括:名字,值,过期时间,路径和域。其中域能指定某一个域比如,相当于总店招牌,比如宝洁公司,也能指定一个域下的具体某台机器比如 或 ,能用飘柔来做比。路径就是跟在域名后面的 URL 路径,比如/ 或/foo 等等,能用某飘柔专柜做比。路径和域合在一起就构成了 cookie 的作用范围。如果不设置过期时间,则表示这个 cookie 的生命期为浏览器会话期间,只要关闭浏览器窗口,cookie
10、 就消失了。这种生命期为浏览器会话期的 cookie 被称为会话 cookie。会话 cookie 一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览器就会把 cookie 保存到硬盘上,关闭后再次打开浏览器,这些cookie 仍然有效直到超过设定的过期时间。存储在硬盘上的 cookie 能在不同的浏览器进程间共享,比如两个 IE 窗口。而对于保存在内存里的 cookie,不同的浏览器有不同的处理方式。对于 IE,在一个打开的窗口上按Ctrl-N(或从文件菜单)打开的窗口能和原窗口共享,而使用其他方式新开的 IE 进程则不能共享已打开的窗口的内存 coo
11、kie;对于 Mozilla Firefox0.8,所有的进程和标签页都能共享同样的 cookie。一般来说是用 javascript 的 window.open 打开的窗口会和原窗口共享内存 cookie。浏览器对于会话 cookie 的这种只认 cookie 不认人的处理方式经常给采用session 机制的 web 应用程式研发者造成非常大的困扰。下面就是个 goolge 设置 cookie 的响应头的例子HTTP/1.1 302 FoundLocation: http:/ PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:
12、S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=Content-Type: text/html这是使用 HTTPLook 这个 HTTP Sniffer 软件来俘获的 HTTP 通讯纪录的一部分浏览器在再次访问 goolge 的资源时自动向外发送 cookie使用 Firefox 能非常容易的观察现有的 cookie 的值使用 HTTPLook 配合 Firefox 能非常容易的理解 cookie 的工作原理。IE 也能设置在接受 cookie 前询问这是个询问接受 cookie 的对话框。四、
13、理解 session 机制session 机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程式需要为某个客户端的请求创建一个 session 的时候,服务器首先检查这个客户端的请求里是否已包含了一个 session 标识 - 称为 session id,如果已包含一个 session id 则说明以前已为此客户端创建过 session,服务器就按照 session id 把这个 session 检索出来使用(如果检索不到,可能会新建一个) ,如果客户端请求不包含 session id,则为此客户端创建一个 session 并且生成一个和此 ses
14、sion 相关联的 session id,session id 的值应该是个既不会重复,植蝗菀妆徽业焦媛梢苑略斓淖址?飧?ession id 将被在本次响应中返回给客户端保存。保存这个 session id 的方式能采用 cookie,这样在交互过程中浏览器能自动的按照规则把这个标识发挥给服务器。一般这个 cookie 的名字都是类似于 SEEESIONID,而。比如 weblogic 对于 web 应用程式生成的cookie, JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,他的名字就是 J
15、SESSIONID。由于 cookie 能被人为的禁止,必须有其他机制以便在 cookie 被禁止时仍然能够把session id 传递回服务器。经常被使用的一种技术叫做 URL 重写,就是把 session id 直接附加在 URL 路径的后面,附加方式也有两种,一种是作为 URL 路径的附加信息,表现形式为 http:/./xxx;jsessionid=ByOK . 99zWpBng!-145788764 另一种是作为查询字符串附加在 URL 后面,表现形式为 http:/./xxx?jsessionid=ByOK . 99zWpBng!-145788764这两种方式对于用户来说是没有差别
16、的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把 session id 的信息和正常程式参数区分开来。为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个 session id。另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把 session id 传递回服务器。这种技术目前已较少应用,笔者接触过的非常古老的 iPlanet6(SunONE 应用服务器的前身)就使用了这种技术。实际上这种技术能简单的用对 action 应用 URL 重写来代替。在谈论 session 机制的时候,常常听到这样一种误解“只要关闭浏览器,session 就消失了”。其实能想象一下会员卡的例子,除非顾客主动对店家提出销卡,否