java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
这篇文章主要介绍了 servlet 之 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。)
Session 的隐藏 Cookie,我们可以做个小实验来验证下,在【myservlet】这个 web 工程下创建两个 Servlet,分别命名为 SessionDemo1 和 SessionDemo2:
在 SessionDemo1 代码为:
- HttpSession session = request.getSession();
- String data = "Message from SessionDemo";
- 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 对象的 invalidate() 方法,将某个 Session 进行立刻销毁。
对此,如果我们要覆盖一个 Session 的 cookie 并保存在硬盘文件中,我们设置的 cookie 有效时间就不要超过服务器默认的 session-timeout 时间。
2,覆盖有效路径:如果我们创建一个 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 SessionDemo";
- 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 来获取之前保存的数据。
来源: http://www.phperz.com/article/18/0102/355933.html