httpSession的正确理解

 关于HttpSession的误解实在是太多了,原本是一个很简单的问题,怎会搞的如此的复杂呢?下面说说个人理解吧:html

一个session就是一系列某用户和服务器间的通信。服务器有能力分辨出不一样的用户。一个session的创建是从一个用户向服务器发第一个请求开始,而以用户显式结束或session超时为结束。
其工做原理是这样的:
1.当一个用户向服务器发送第一个请求时,服务器为其创建一个session,并为此session建立一个标识号;
2.这个用户随后的全部请求都应包括这个标识号。服务器会校对这个标识号以判断请求属于哪一个session。
这种机制不使用IP做为标识,是由于不少机器是经过代理服务器方式上网,无法区分每一台机器。
对于session标识号(sessionID),有两种方式实现:cookies和URL重写。java

HttpSession的使用
咱们来看看在API中对session是如何定义和操做的。
当须要为用户端创建一个session时,servlet容器就建立了一个HttpSession对象。其中存储了和本session相关的信息。因此,在一个servlet中有多少个不一样用户链接,就会有多少个HttpSession对象。
使用的机理是:
1.从请求中提取HttpSession对象;
2.增长或删除HttpSession中的属性;
3.根据须要关闭HttpSession或使其失效。web

在请求中有两个重载的方法用来获取HttpSession对象。
HttpSession getSession(boolean create)/getSession();做用是提取HttpSession对象,若是没有自动建立。算法

获取到HttpSession对象后,咱们就须要使用HttpSession的某些方法去设置和更改某些参数了。如:
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);数据库

在javax.servlet.http包里一共定义了四个session监听器接口和与之关联的两个session事件。分别是:
HttpSessionAttributeListener and HttpSessionBindingEvent;
HttpSessionBindingListener and HttpSessionBindingEvent;
HttpSessionListener and HttpSessionEvent;
HttpSessionActivationListener and HttpSessionEvent.apache

他们的继承关系是:
全部四个接口的父类是java.util.EventListener;
HttpSessionEvent扩展java.util.EventObject;
而HttpSessionBindingEvent又扩展了HttpSessionEvent。编程

如下分别详述:
HttpSessionAttributeListener
当session中的属性被添加,更改,删除时获得通知。这个接口上节讲过,主要看其它三个。api

HttpSessionBindingListener
当一个实现了HttpSessionBindingListener的类被加入到HttpSession中(或从中移出)时,会产生HttpBindingEvent事件,而这些事件会被它自己接收到。
本接口定义了两个方法:
void valueBound(HttpSessionBindingEvent e);
void valueUnbound(HttpSessionBindingEvent e);
当多个实现了HttpSessionBindingListener的类被加入到HttpSession中时,各种的方法只对本类感兴趣,不会去理会其它类的加入。
即便是同一类的不一样实例间,也是互不关心的(各扫门前雪)。浏览器

咱们能够看到前两个接口都对HttpSessionBindingEvent事件作出反应,但机理不一样。
HttpSessionAttributeListener是在web.xml中登记的,servlet容器仅建立一个实例,来为任何在session中增长属性的servlet服务。触发事件的对象是全部能够转换为Object的实例。
HttpSessionBindingListener不用在web.xml中登记,在每一个servlet中用new建立实例,且仅对本实例向session中的加入(或移出)感兴趣。触发事件的对象仅仅是本身。tomcat

HttpSessionListener
对于session的建立和取消感兴趣。须要在web.xml中登记。
共有两个方法:
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
使用它咱们能够容易的建立一个类来对session计数。
也许咱们会简单的考虑使用sessionDestroyed方法来在session结束后作一些清理工做。可是,请注意,当这个方法被调用的时候,session已经结束了,你不能从中提取到任何信息了。所以,咱们要另辟蹊径。
一种一般采用的方法是使用HttpSessionBindingListener接口。在session建立时增长一个属性,而在session结束前最后一件事将这个属性删除,这样就会触发valueUnbound方法,全部对session的清理工做能够在这个方法中实现。

HttpSessionActivationListener
当session在分布式环境中跨JVM时,实现该接口的对象获得通知。共两个方法:
void sessionDidActivate(HttpSessionEvent se);
void sessionWillPassivate(HttpSessionEvent se);


一、HTTP协议自己是“链接-请求-应答-关闭链接”模式的,是一种无状态协议(HTTP只是一个传输协议);
二、Cookie规范是为了给HTTP增长状态跟踪用的(若是要精确把握,建议仔细阅读一下相关的RFC),但不是惟一的手段;
三、所谓Session,指的是客户端和服务端之间的一段交互过程的状态信息(数据);这个状态如何界定,生命期有多长,这是应用自己的事情;
四、因为B/S计算模型中计算是在服务器端完成的,客户端只有简单的显示逻辑,因此,Session数据对客户端应该是透明的不可理解的而且应该受控于服务端;Session数据要么保存到服务端(HttpSession),要么在客户端和服务端之间传递(Cookie或url rewritting或Hidden input);
五、因为HTTP自己的无状态性,服务端没法知道客户端相继发来的请求是来自一个客户的,因此,当使用服务端HttpSession存储会话数据的时候客户端的每一个请求都应该包含一个session的标识(sid, jsessionid 等等)来告诉服务端;
六、会话数据保存在服务端(如HttpSession)的好处是减小了HTTP请求的长度,提升了网络传输效率;客户端session信息存储则相反;
七、客户端Session存储只有一个办法:cookie(url rewritting和hidden input由于没法作到持久化,不算,只能做为交换session id的方式,即a method of session tracking),而服务端作法大体也是一个道理:容器有个session管理器(如tomcat的org.apache.catalina.session包里面的类),提供session的生命周期和持久化管理并提供访问session数据的api;
八、使用服务端仍是客户端session存储要看应用的实际状况的。通常来讲不要求用户注册登陆的公共服务系统(如google)采用cookie作客户端session存储(如google的用户偏好设置),而有用户管理的系统则使用服务端存储。缘由很显然:无需用户登陆的系统惟一可以标识用户的就是用户的电脑,换一台机器就不知道谁是谁了,服务端session存储根本无论用;而有用户管理的系统则能够经过用户id来管理用户我的数据,从而提供任意复杂的个性化服务;
九、客户端和服务端的session存储在性能、安全性、跨站能力、编程方便性等方面都有必定的区别,并且优劣并不是绝对(譬如TheServerSide号称不使用HttpSession,因此性能好,这很显然:一个具备上亿的访问用户的系统,要在服务端数据库中检索出用户的偏好信息显然是低效的,Session管理器无论用什么数据结构和算法都要耗费大量内存和CPU时间;而用cookie,则根本不用检索和维护session数据,服务器能够作成无状态的,固然高效);
十、所谓的“会话cookie”简单的说就是没有明确指明有效期的cookie,仅在浏览器当前进程生命期内有效,能够被后继的Set-Cookie操做清除掉。
当程序须要为某个客户端的请求建立一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id,若是已包含一个session id则说明之前已经为此客户端建立过session,服务器就按照session id把这个 session检索出来使用(若是检索不到,可能会新建一个),若是客户端请求不包含session id,则为此客户端建立一个session而且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id将被在本次响应中返回给客户端保存。
保存这个session id的方式能够采用cookie,这样在交互过程当中浏览器能够自动的按照规则把这个标识发挥给服务器。通常这个cookie的名字都是相似于SEEESIONID.
一、session在什么时候被建立
一个常见的误解是觉得session在有客户端访问时就被建立,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被建立,注意若是JSP没有显示的使用 <% @page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句 HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的 session对象的来历。因为session会消耗内存资源,所以,若是不打算使用session,应该在全部的JSP中关闭它。
二、存放在session中的对象必须是可序列化的吗
不是必需的。要求对象可序列化只是为了session可以在集群中被复制或者可以持久保存或者在必要时server可以暂时把session交换出内存。
三、如何才能正确的应付客户端禁止cookie的可能性
对全部的URL使用URL重写,包括超连接,form的action,和重定向的URL,具体作法参见:
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
Instead, use the HttpServletResponse.encodeURL() method, for example:
out.println("<a href=/""     + response.encodeURL("myshop/catalog.jsp")      + "/">catalog</a>");
Calling the encodeURL() method determines if the URL needs to be rewritten, and if so, it rewrites it by including the session ID in the URL. The session ID is appended to the URL and begins with a semicolon.

In addition to URLs that are returned as a response to WebLogic Server, also encode URLs that send redirects. For example:
if (session.isNew()) response.sendRedirect (response.encodeRedirectUrl(welcomeURL));
四、开两个浏览器窗口访问应用程序会使用同一个session仍是不一样的session 参见第三小节对cookie的讨论,对session来讲是只认id不认人,所以不一样的浏览器,不一样的窗口打开方式以及不一样的cookie存储方式都会对这个问题的答案有影响。
相关文章
相关标签/搜索