大家好,又见面了,我是你们的朋友全栈君。
原文章地址。 整理下版面,看起来舒服一些!
一个session就是一系列某用户和服务器间的通讯。服务器有能力分辨出不同的用户。一个session的建立是从一个用户向服务器发第一个请求开始,而以用户显式结束或session超时为结束。 其工作原理是这样的:
这种机制不使用IP作为标识,是因为很多机器是通过代理服务器方式上网,没法区分每一台机器。 对于session标识号(sessionID),有两种方式实现:cookies和URL重写。
我们来看看在API中对session是如何定义和操作的。 当需要为用户端建立一个session时,servlet容器就创建了一个HttpSession对象。其中存储了和本session相关的信息。所以,在一个servlet中有多少个不同用户连接,就会有多少个HttpSession对象。 使用的机理是:
在请求中有两个重载的方法用来获取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.
他们的继承关系是: 所有四个接口的父类是java.util.EventListener; HttpSessionEvent扩展java.util.EventObject; 而HttpSessionBindingEvent又扩展了HttpSessionEvent。
以下分别详述: HttpSessionAttributeListener 当session中的属性被添加,更改,删除时得到通知。这个接口上节讲过,主要看其它三个。
当一个实现了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中的加入(或移出)感兴趣。触发事件的对象仅仅是自己。
对于session的创建和取消感兴趣。需要在web.xml中登记。 共有两个方法:
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
使用它我们可以容易的创建一个类来对session计数。 也许我们会简单的考虑使用sessionDestroyed方法来在session结束后做一些清理工作。 但是,请注意,当这个方法被调用的时候,session已经结束了,你不能从中提取到任何信息了。因此,我们要另辟蹊径。 一种通常采用的方法是使用HttpSessionBindingListener接口。在session创建时增加一个属性,而在session结束前最后一件事将这个属性删除,这样就会触发valueUnbound方法,所有对session的清理工作可以在这个方法中实现。
当session在分布式环境中跨JVM时,实现该接口的对象得到通知。共两个方法:
void sessionDidActivate(HttpSessionEvent se);
void sessionWillPassivate(HttpSessionEvent se);
当程序需要为某个客户端的请求创建一个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在有客户端访问时就被创建,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)
这样的语句时才被创建,注意如果JSP没有显示的使用 <% @page session="false"%>
关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句 HttpSession session = HttpServletRequest.getSession(true);
这也是JSP中隐含的 session对象的来历。由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。
不是必需的。要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。
对所有的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));
参见第三小节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器,不同的窗口打开方式以及不同的cookie存储方式都会对这个问题的答案有影响。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/158680.html原文链接:https://javaforall.cn