在上一篇中我们学习了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代码为:

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

在SessionDemo2代码为:

     HttpSession session = request.getSession();
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返回给客户端,修改后代码如下:

     HttpSession session = request.getSession();
String data = "Message from SessionDemo1";
session.setAttribute("data", data); Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(30*60);
cookie.setPath("/myservlet");
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来获取之前保存的数据。

Servlet的学习之Session(2)的更多相关文章

  1. Servlet的学习之Session(3)

    在上一篇<Servlet的学习之Session(2)>我们知道了Session能实现一个会话过程中保存数据或者多个会话中实现同一个Session的关键因素就是Cookie,只是Cookie ...

  2. Servlet的学习之Session(1)

    在学习完了Servlet中的Cookie技术后,我们再来学习另一个能保存会话数据的技术——Session. Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其 ...

  3. Servlet的学习之Session(4)

    在本篇中,我们来使用Session完成一个用户登录的案例,前提声明:这个案例主要用于学习Session技术,是属于比较简单的类型,以后会采用MVC模式来开发登录,那就会比较复杂. 现在大多数网站都提供 ...

  4. Servlet的学习之Session(5)

    在上一篇中我们介绍了如果使用Session来做一个简单的用户登录案例,在本篇中我们继续使用Session技术来做一个防止表单重复提交的案例. 这是一个很重要的知识点,在很多框架中都有防止表单重复提交的 ...

  5. JavaWeb之Servlet:Cookie 和 Session

    会话 现实生活中我们会用手机跟对方对话,拿起手机,拨号,然后对面接听,跟着互相通话,最后会话结束. 这个过程也可以用我们的B/S模式来描述: 打开浏览器—>输入地址->发出请求->服 ...

  6. Servlet的学习之Cookie

    从本篇开始学习Servlet技术中的Cookie专题. 首先来了解什么是“会话”.会话是web技术中的一个术语,可以简单的理解为:用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭 ...

  7. Servlet的学习之Filter过滤器技术(1)

    本篇将讲诉Servlet中一项非常重要的技术,Filter过滤器技术.通过过滤器,可以对来自客户端的请求进行拦截,进行预处理或者对最终响应给客户端的数据进行处理后再输出. 要想使用Filter过滤器, ...

  8. Servlet的学习(四)

    在本篇的Servlet的学习中,主要来学习由使用MyEclipse来开发Servlet的一些小细节. 细节一:在web.xml中可以对同一个Servlet配置多个对外访问路径,并如果在web.xml中 ...

  9. Servlet的学习之Request请求对象(3)

    本篇接上一篇,将Servlet中的HttpServletRequest对象获取RequestDispatcher对象后能进行的[转发]forward功能和[包含]include功能介绍完. 首先来看R ...

随机推荐

  1. 一天一个类--NIO 之Buffer

    java.nio  --- 定义了 Buffer 及其数据类型相关的子类.其中被 java.nio.channels 中的类用来进行 IO 操作的 ByteBuffer 的作用非常重要. java.n ...

  2. POJ 3261 可重叠的 k 次最长重复子串【后缀数组】

    这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...

  3. 设计模式(十)享元模式Flyweight(结构型)

    设计模式(十)享元模式Flyweight(结构型) 说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释 ...

  4. 基于visual Studio2013解决C语言竞赛题之0510求最大和

     题目

  5. 飞翔(LIS变形)

    飞翔 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 鹰最骄傲的就是翱翔,但是鹰们互相都很嫉妒别的鹰比自己飞的快,更嫉妒其他的鹰比自己飞行的有技巧.于是,他们决定举办一场 ...

  6. 非确定有限状态自动机的构建(二)——将CharVal转换为NFA

    保留版权,转载注明出处:潘军彪的个人博客(http://blog.csdn.net/panjunbiao/article/details/9378933) 将上下文无关文法读入内存之后,可以将它转换成 ...

  7. [转]php连接postgresql

    首先推荐一下postgres数据库,免费,强大,甚至某些方面比商业数据库还要好,大家可以试试. 安装: 附安装图解(网上找的):http://blog.sina.com.cn/s/blog_5edb7 ...

  8. 安装MyEclipse Color Themes

    下载地址:http://eclipsecolorthemes.org/?list=toppicks&lang=html 安装步骤如下: 1.Import---Preferences 2.选择下 ...

  9. 自定义类似QMutexLocker的CMutexLocker

    最近做项目遇到一个需求,有一个buttonSlot()执行要耗点时间,为了防止用户无限制的乱点出现问题,考虑加一个互斥锁,使得每次执行完后才允许执行下一次.大概意思是: //QMutex  m_mut ...

  10. Android GsonUtils工具类

    有那么一个开源jar包,叫gson 可以很方便的将java中的对象和字符串相互转化,数据传输和处理的时候,用到的可能性很大 https://github.com/google/gson http:// ...