zoukankan      html  css  js  c++  java
  • Servlet的学习之Session(2)

      在上一篇中我们学习了Session对象默认在一个会话过程中,由服务器创建,能保存在这个会话过程中用户访问多个web资源时产生的需要保存的数据,并在访问服务器中其他web资源时可以将这些数据从Session中取出并为之使用。

      然而在一个会话过程后就将无法再取到Session对象(因为cookie不存在了,原因下面将阐明),可能导致的是用户误将浏览器关闭而使保存在Session中的数据无法再取到,因此如果我们能将多个会话同时使用同一个Session对象就能满足用户“刁蛮”的需求。

      在前一篇的最开始就说过,在默认情况下,一个浏览器独享一个Session。请注意,这里是默认情况下, 而我们有了新需求,就要打破默认情况(比如默认情况下Cookie也是在一个会话结束后消失,但是我们设置了setMaxAge后就能在硬盘中生存),做到多个浏览器共享一个Session,同时这也意味着一台用户主机有一个Session,而不管他开了多少个浏览器。

      那么首先我们必须先了解Session的底层工作原理。我们还是先看在一个会话过程中,同一个浏览器在访问多个web资源的情况好了,大致分为以下几个步骤:

      1,浏览器访问某个Servlet,这时如果服务器要从请求对象中获取Session对象(第一次获取也是创建),那么服务器会为这个Session对象创建一个id:JSESSIONID

      2,同时在对浏览器的响应过程中,这个Session会将JSESSIONID这个id以Cookie形式回送给客户端浏览器,记住,这时候Cookie服务器没有设置有效时间,因此是存在浏览器的缓存中,而不是在硬盘文件。

      3,当用户继续在这个会话过程中访问其他Servlet,这时候这个Servlet再从请求对象中获取Session对象,注意这时候获取Session对象是从浏览器发来的请求中查询是否有名为JSESSIONID的这个Cookie,如果有,那么这个Session就不用再创建,而是直接根据查询服务器中这个相同JSESSIONID值的Session,换句话说就可以取得之前存在这个Session中的数据。

      总结来说,Session是基于Cookie的。

      (:cookie并不是万能的,Session首先是依据cookie,但是有时候cookie不能用,这时候Session会查询发来请求的URL地址是否有JSESSIONID,具体请看《Servlet的学习之Session(3)》。)

      我们可以通过下面这个动图来看一看:

      

      对于这个Session的隐藏Cookie,我们可以做个小实验来验证下,在【myservlet】这个web工程下创建两个Servlet,分别命名为SessionDemo1和SessionDemo2:

    在SessionDemo1代码为:

    1     HttpSession session = request.getSession();
    2     String data = "Message from SessionDemo1";
    3     session.setAttribute("data", data);

    在SessionDemo2代码为:

    1     HttpSession session = request.getSession();
    2     System.out.println((String)session.getAttribute("data"));

    我们在浏览器中打开HttpWatch,来访问SessionDemo1,因为是首次访问Servlet,查看SessionDemo1给浏览器的响应:

      

    确确实实服务器发送回浏览器有这个JSESSIONID名称的Cookie,这时候如果我们再在打开的浏览器去访问SessionDemo2,那么在HttpWatch中观察请求包的内容发现:

      

    再次访问服务器时,浏览器就会带着这个名为JSESSIONID的Cookie给服务器,服务器正是通过这个cookie中的JSESSIONID值去服务器中查找之前为该浏览器创建的Session。

      如果我们将浏览器关闭,由于这个cookie没有设置“setMaxAge”,因此这个cookie只存在于浏览器的缓冲,浏览器关闭即被销毁。如果想使关闭浏览器之后,Session还能存在,我们就要人为的覆盖这个Session的cookie,并设置覆盖cookie的有效时间和有效路径。而这个cookie的值,也就是JSESSIONID的值,可以通过Session的getId()方法得到。

      1,覆盖有效时间:

      注意,服务器在为浏览器创建Session后,在用户没有操作的情况下(或者浏览器关闭后)默认为其维护30分钟。这点可以从Tomcat的【web.xml】文件中可以看出:

      

    当然我们从这里也可以修改服务器默认的销毁无操作的Session时间。

      当然如果我们不要全局设置所有服务器中Session的销毁时间,就在每个web应用中的web.xml文件中自定义添加<session-config>和<session-timeout>进行设置。

      :我们还可以通过Session对象的invalidate()方法,将某个Session进行立刻销毁。

      对此,如果我们要覆盖一个Session的cookie并保存在硬盘文件中,我们设置的cookie有效时间就不要超过服务器默认的session-timeout时间。

      2,覆盖有效路径:

      我们在《Servlet的学习之Cookie》中知道,如果我们创建一个Cookie对象,没有设置“setPath”,那么Cookie的有效路径为创建该Cookie的程序(通常为某个Servlet),即只有访问了这个程序时浏览器才会带着Cookie过去,那实在是“人脉不通”,访问这个web应用的其他资源就无法再使用Session了。

      我们看看刚才的第一次访问Servlet时,服务器为浏览器创建的Session中的cookie的有效路径:

      

    可以看到这个服务器默认将JSESSIONID这个cookie的有效路径设置为创建这个Session的web工程根目录。所以我们要覆盖Session中的cookie时也应该设置路径为该web工程根目录。

      好,接下来对上面那个Servlet的例子进行改造,我们只需要在SessionDemo1中修改就行,因为这个首次将Session的cookie返回给客户端,修改后代码如下:

    1     HttpSession session = request.getSession();
    2     String data = "Message from SessionDemo1";
    3     session.setAttribute("data", data);
    4         
    5     Cookie cookie = new Cookie("JSESSIONID", session.getId());
    6     cookie.setMaxAge(30*60);
    7     cookie.setPath("/myservlet");
    8     response.addCookie(cookie);

    这样,当我们打开浏览器访问了SessionDemo1之后,就能在存放cookie的目录中找到该cookie,如果我们通过HttpWatch来查看可以看到重名的这个cookie:

      

    虽然JSEESIONID这个cookie重名了,没有关系,因为其值都是一样的,并且如果我们将浏览器关闭后,没有设置cookie有效时间的(也是原先Session发来的)cookie将不复存在(存在浏览器缓存中,浏览器关闭就被销毁),这时重新打开一个浏览器,再去访问SessionDemo2依然能获取到原来Session中保存的内容:

      

    注意,这是另外打开浏览器窗口访问的SessionDemo2!!另附:

      

      通过这里我们可以看到,我们人为地将原先Session定义的cookie给替换了,而Session并不知道,只要能获得“JSESSIONID”这个cookie,它就认为cookie是存在的,可以从这个cookie中id值获取以前保存的信息,因此我们实现了一台主机共享一个Session,此时,当浏览器关闭,或者说结束一个会话后,依然能获取Session来获取之前保存的数据。

  • 相关阅读:
    考察数据结构(An Extensive Examination of Data Structures)
    考察数据结构——第一部分:数据结构简介[译]
    老生常谈
    使用DataSet的ReadXml和WriteXml方法
    要掌握Sql Server,我还差得远啊!
    新浪短信Web Service
    还是水晶报表
    两种报表组件的功能分析
    无限级分类(非递归算法/存储过程版/GUID主键)完整数据库示例_(4)显示记录
    c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区别
  • 原文地址:https://www.cnblogs.com/fjdingsd/p/4905476.html
Copyright © 2011-2022 走看看