Session机制

Session机制
除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,响应的也增加了服务器的存储压力。
Session技术是服务端的解决方案,它是通过服务器来保持状态的。由于Session这个词汇包含的语义很多,因此需要在这里明确Session的含义。
首先,我们通常把Session翻译成会话,因此我们可以把客户端浏览器与服务器之间一系列交互的动作称为一个Session。从这个语义出发,我们会提到Session持续的时间,会提到在Session过程中进行了什么操作等等;其次,Session指的是服务器端为客户端所开辟的存储空间,在其中保存的信息就是用于保持状态。从这个语义出发,我们则会提到往Session中存放什么内容,如何根据键值从Session中获取匹配的内容等。
要使用Session,第一步当然是创建Session了。那么Session在何时创建呢?当然还是再服务器端程序运行的过程中创建的。不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。
在创建了Session的同时,服务器会为该Session生成唯一的SessionId,而这个SessionId在随后的请求中会被用来重新获得已经创建的Session,在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了。
而这些内容只会保存在服务器中,发到客户端的只有SessionId,当客户端再次发送请求的时候,会将这个SessionId带上,服务器接收到请求之后就根据SessionId找到相应的Session,从而再次使用。正是这样一个过程,用户的状态得以保持。



什么是Session
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器吧客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的"客户明细表"来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。


Session的生命周期
Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session,如果Session内容太过复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet等程序时,才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。



Session的有效期
由于会有越来越多的用户访问服务器,因此Session也会越来越多。为了防止内存溢出,服务器会把长时间没有活跃的Session从内存删除。这个时间就Session的超时时间,如果超过了超时时间没有访问服务器,Session就自动失效了。
Session的超时时间为maxInactiveInterval属性,可以通过getMaxInactiveInterval()获取,通过setMaxInactiveInterval()修改。
Session的超时时间也可以在web.xml中修改,另外,调用Session的invalidate()方法可以使Session失效。


Session的常用方法
void setAttribute(String value,Object value):设置Session属性。value参数可以为任何Java Object。通常为JavaBean,value信息不宜过大。
String getAttribute(String attribute):返回Session属性
Enumeration getAttributeNames():返回Session中存在的属性名
void removeAttribute(String attribute):移除Session属性
String getId():返回Session的ID。该ID由服务器自动创建,不会重复。
long getCreationTime():返回Session的创建日期。返回类型为long,常被转化为Date类型,例如:Date createTime = new Date(session.getCreationTime())
long getLastAccessedTime():返回Session的最后活跃时间。返回类型为long int 
getMaxInactiveInterval():返回Session的超时时间。单位为秒。超过该时间没有访问,服务器认为该Session失效
void setMaxInactiveInterval(int second):设置Session的>超时时间。单位为秒 
void putValue(String attribute, Object value):不推荐的方法。已经被setAttribute(String attribute, Object Value)替代
Object getValue(String attribute):不被推荐的方法。已经被getAttribute(String attr)替代
boolean isNew():返回该Session是否是>新创建的 void invalidate():使该Session失效


Tomcat中Session的默认超时时间为20分钟,通过setMaxInactiveInterval(int second)修改超时时间。
也可以修改web.xml中的默认超时时间,例如修改成60分钟
<session-config>
   <session-timeout>60</session-timeout>
</session-config>


注意:参数的单位为分钟,而setMaxInactiveInterval(int s)单位为秒。
在server.xml中定义context时采用如下定义(单位为秒):
<Context path="/livsorder" docBase="/home/httpd/html/livsorder" defaultSessionTimeOut="3600" isWARExpanded="true"
    isWARValidated="false" isInvokerEnabled="true"
    isWorkDirPersistent="false"/>




Session对浏览器的要求
虽然Session保存在服务器,对客户端是透明的,它的运行仍需要客户端浏览器的支持。这是因为Session需要使用Cookie作为识别标识。
Http协议是无状态的,Session不能根据http连接判断是否是同一用户。因此服务器向客户端发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值),Session根据该Cookie来判断是否是同一用户。
该Cookie是服务器自动生成的,它的maxAge属性一般为-1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。
因此同一个机器的两个浏览器窗口访问服务器时,会生成不同的Session,但是由浏览器窗口内的链接,脚本打开的新窗口(也就是说不是由双击桌面浏览器图标打开的窗口)除外,这类子窗口共享父窗口的Cookie,因此会共享一个Session。
注意:新打开的窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择“在新窗口打开时”,子窗口便可以访问父窗口的Session。
如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:URL地址重写。



URL地址重写
URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。HttpServletResponse类提供了encodeURL(Stringurl)实现URL地址重写,例如:
<td>
    <a href="<%=response.encodeURL("index.jsp?c=1&wd=Java") %>"> 
    Homepage</a>
</td>
该方法会自动判断客户端是否支持Cookie。如果客户端支持Cookie,会将URL原封不动地输出来。如果客户端不支持Cookie,则会将用户Session的id重写到URL中。重写后的输出可能是这样的:
<td>
    <a href="index.jsp;jsessionid=0CCD096E7F8D97B0BE608AFDC3E1931E?c=1&wd=Java">Homepage</a>
</td>
即在文件名的后面,在URL参数的前面添加了字符串“;jsessionid=XXX”。其中XXX为Session的id。分析一下可以知道,增添的jsessionid字符串既不会影响请求的文件名,也不会影响提交的地址栏参数。用户单击这个链接的时候会把Session的id通过URL提交到服务器上,服务器通过解析URL地址获得Session的id。


如果是页面重定向(Redirection),URL地址重写可以这样写:
<%
    if(“administrator”.equals(userName)) {
        response.sendRedirect(response.encodeRedirectURL(“administrator.jsp”));
        return;
    }
%>
效果跟response.encodeURL(String url)是一样的:如果客户端支持Cookie,生成原URL地址,如果不支持Cookie,传回重写后的带有jsessionid字符串的地址。
对于WAP程序,由于大部分的手机浏览器都不支持Cookie,WAP程序都会采用URL地址重写来跟踪用户会话。
注意:TOMCAT判断客户端浏览器是否支持Cookie的依据是请求中是否含有Cookie。尽管客户端可能会支持Cookie,但是由于第一次请求时不会携带任何Cookie(因为并无任何Cookie可以携带),URL地址重写后的地址中仍然会带有jsessionid。当第二次访问时服务器已经在浏览器中写入Cookie了,因此URL地址重写后的地址中就不会带有jsessionid了。
由于Cookie可以被人为的禁止,必须有其他机制以便在Cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种: 一种是作为URL路径的附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 一种是作为查询字符串附加在URL后面,表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如下面的表单:
<form name="testform" action="/xxx">
    <input type="text">
</form>
在被传递给客户端之前将被改写成:
<form name="testform" action="/xxx">
    <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
    <input type="text">
</form>
在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个 session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。

恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。


Session中禁止使用Cookie

既然WAP上大部分的客户浏览器都不支持Cookie,索性禁止会话使用Cookie,统一使用URL地址重写会更好一些.Java Web规范支持通过配置的方式禁用Cookie。下面举例说一下怎样通过配置禁止使用的cookie。


打开项目sessionWeb的WebRoot目录下的META-INF文件夹(跟WEB-INF文件夹同级,如果没有则创建),打开context.xml(如果没有则创建),编辑内容如下:/ META-INF / context .xml:
<?xml version ='
    1.0'coding ='UTF-8'?> <Context path =“/ sessionWeb”cookies =“false”>
</ Context>

或者修改Tomcat全局的conf / context.xml,修改内容如下:context.xml:
<! - 将为每个web应用程序加载此文件的内容 - >
<Context cookies =“false”>
    <! - ...中间代码略 - >
</ Context>

部署后TOMCAT便不会自动生成名JSESSIONID的饼干,会议也不会以饼干为识别标志,而仅仅以重写后的URL地址为识别标志了

注意:该配置只是禁止会话使用的Cookie作为识别标志,并不能阻止其他的Cookie读写。也就是说服务器不会自动维护名为JSESSIONID的Cookie了,但是程序中仍然可以读写其他的Cookie.Cookie


和Session的区别:
1.cookie数据存放在客户的浏览器上,会话数 据放在服务器上;
2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用会话;
3.session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用COOKIE;
4. 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K;


Cookie和Session的方案虽然分别属于客户端和服务端,但是服务端的会话的实现对客户端的cookie的有依赖关系的,上面我讲到服务端执行会话机制时候会生成会话的ID值,这个ID值会发送给客户端,客户端每次请求都会把这个ID值放到HTTP请求的头部发送给服务端,而这个ID值在客户端会保存下来,保存的容器就是饼干,因此当我们完全禁掉浏览器的饼干的时候,服务端的会话也会不能正常使用(注意:有些资料说ASP解决这个问题,当浏览器的cookie的 禁掉,服务端的会话任然可以正常使用,ASP我没试验过,但是对于网络上很多用PHP和JSP编写的网站,我发现禁掉的cookie,网站的会话都无法正常的访问)。






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值