Session如何工作。

同一个客户端每次和服务端交互时,不需要每次都传回所有的Cookie值,而是只要传回一个ID,这个ID是客户端第一次访问服务器时生成的,而且每个客户端是唯一的。这样每个客户端就由了一个唯一的ID,客户端只要传回这个ID就行了,这个ID通常是NAME为JESIONID的一个Cookie。

Session和Cookie

下面详细讲一下Session是如何基于Cookie来工作的。实际上有以下三种方式可以让Session正常工作。

  •     基于URL Path Parameter,默认支持。
  •     基于Cookie,如果没有修改Context容器的Cookies标识,则默认也是支持的。
  •     基于SSL,默认不支持,只有connector.getAttribute("SSLEnabled")为TRUE时才支持。

在第一种情况下,当浏览器不支持Cookie功能时,浏览器会将用户的SessionCookieName重写到用户请求的URL参数中,他的传递格式如/path/Servlet;name=value;name2=value2?Name3=value3,其中“Servlet;”后面的K-V就是要传递的Path Parameters,服务器会从这个Path Parameters中拿到用户配置的SessionCookieName。关于这个SessionCookieName,如果在web.xml中配置session-config配置项,其cookie-config下的name属性就是这个SessionCookieName的值。如果没有配置session-config配置项,默认的SessionCookieName就是大家熟悉的“JSESSIONID”。需要说明的一点是,与Session关联的Cookie与其他Cookie没有什么不同。接着Request根据这个SessionCookieName到Parameters中拿到Session ID并设置到request.setRequestedSessionId中。

请注意,如果客户端也支持Cookie,则Tomcat仍然会解析Cookie中的Session ID,并会覆盖URL中的Session ID。

如果是第三种情况,则会根据java.servlet.request.ssl_session属性值设置Session ID。

Session如何工作

有了Session ID,服务端就可以创建HttpSession对象了,第一次触发通过request.getSession()方法。如果当前的Session ID还没有对应的HttpSession对象,那么就创建一个新的,并将这个对象加到org.apache.catalina.Manager的sessions容器中保存。Manager类将管理所有Session的声明周期,Session过期将被回收,服务器关闭,Session将被序列化到磁盘等。只要这个HttpSession对象存在,用户就可以根据Session ID来获取这个对象,也就做到了对状态的保持。

从request.getSession中获取的HttpSession对象实际上是StandardSession对象的门面对象,这与Request和Servlet是一样的原理。下图是Session工作的时序图。

从时序图中可以看出,从Request中获取的Session对象保存在org.apache.catalina.Manager类中,他的实现类是org.apache.catalina.session.StandardManager,通过requestSessionId从StandardManager的sessions集合中取出StandardSession对象。由于一个requestedSessionId对应一个访问的客户端,所以一个客户端也就对应一个StandardSession对象,这个对象正是保存我们创建的Session值的。下面我们看一下StandardManager这个类是如何管理StandardSession的生命周期的。

StandardManager类负责Servlet容器中所有的StandardSession对象的生命周期管理。当Servlet容器重启或关闭时,StandardManager负责持久化没有过期的StandardSession对象,他会将所有的StandardSession对象持久化到一个以“SESSIONS.ser”为文件名的文件中。到Servlet容器重启时,也就是StandardManager初始化时,他会重新读取这个文件,解析出所有Session对象,重新保存在StandardManager的sessions集合中。Session的恢复状态图如下图所示。

当Servlet容器关闭StandardManager类会调用unload方法将sessions集合中的StandardSession对象写到“SESSIONS.ser”文件中,然后在启动时再按照上面的状态图重新恢复,注意要持久化保存在Servlet容器中的Session对象,必须调用Servlet容器的stop和start命令,而不能直接结束(kill)Servlet容器的进程。因为直接结束进程,Servlet容器没有机会调用unload方法来持久化这些Session对象。

另外,在StandardManager的sessions集合中的StandardSession对象并不是永远保存的,否则Servlet容器的内存将很容易被消耗尽,所以必须给每个Session对象定义一个有效时间,超过这个时间则Session对象将被清除。在Tomcat中这个有效时间是60s(maxInactiveInterval属性控制),超过60s该Session将会过期。检查每个Session是否失效是在Tomcat的一个后台线程中完成的(backgroundProcess()方法中)。过期Session的状态图如下图所示。

除了后台进程检查Session是否失效外,当调用request.getSession()时也会检查该Session是否过期。值得注意的是,request.getSession()方法调用的StandardSession永远都会存在,即使与这个客户端关联的Session对象已经过期。如果过期,则又会重新创建一个全新的StandardSession对象,但是以前设置的Session值将会丢失。如果你取到了Session对象,但是通过session.getAttribute取不到前面设置的Session值,请不要奇怪,因为很可能他已经失效了,请检查以下<Manager pathname="" maxInactiveInterval="60" />中maxInactiveInterval配置项的值,如果不想让Session过期则可以设置为-1,但是你要仔细评估一下,网站的访问量和设置的Session的大小,防止将你的Servlet容器内存撑爆。如果不想自动创建Session对象,也可以通过request.getSession(boolean create)方法来判断与该客户端关联的Session对象是否存在。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值