分享
 
 
 

servlet的session管理

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

一、 Servlet 的会话管理机制

根据设计, HTTP 是一种无状态的协议。它意味着 Web 应用并不了解有关同一用户以前请求的信息。维持会话状态信息的方法之一是使用 Servlet 或者 JSP 容器提供的会话跟踪功能。 Servlet API 规范定义了一个简单的 HttpSession 接口,通过它我们可以方便地实现会话跟踪。

HttpSession 接口提供了存储和返回标准会话属性的方法。标准会话属性如会话标识符、应用数据等,都以“名字 - 值”对的形式保存。简而言之, HttpSession 接口提供了一种把对象保存到内存、在同一用户的后继请求中提取这些对象的标准办法。在会话中保存数据的方法是 setAttribute(String s, Object o) ,从会话提取原来所保存对象的方法是 getAttribute(String s) 。

每当新用户请求一个使用了 HttpSession 对象的 JSP 页面, JSP 容器除了发回应答页面之外,它还要向浏览器发送一个特殊的数字。这个特殊的数字称为“会话标识符”,它是一个唯一的用户标识符。此后, HttpSession 对象就驻留在内存之中,等待同一用户返回时再次调用它的方法。

在客户端,浏览器保存会话标识符,并在每一个后继请求中把这个会话标识符发送给服务器。会话标识符告诉 JSP 容器当前请求不是用户发出的第一个请求,服务器以前已经为该用户创建了 HttpSession 对象。此时, JSP 容器不再为用户创建新的 HttpSession 对象,而是寻找具有相同会话标识符的 HttpSession 对象,然后建立该 HttpSession 对象和当前请求的关联。

会话标识符以 Cookie 的形式在服务器和浏览器之间传送。如果客户端不支持 cookie ,运用 url 改写机制来保证会话标识符传回服务器。

二、 Session 事件侦听

HttpSessionBindingEvent 类 \

定义 \

public class HttpSessionBindingEvent extends EventObject

这个事件是在监听到 HttpSession 发生绑定和取消绑定的情况时连通 HttpSessionBindingListener 的。这可能是一个 session 被终止或被认定无效的结果。

事件源是 HttpSession.putValue 或 HttpSession.removeValue 。

构造函数

public HttpSessionBindingEvent(HttpSession session, String name);

通过引起这个事件的 Session 和发生绑定或取消绑定的对象名构造一个新的 HttpSessionBindingEvent 。

方法

1 、 getName

public String getName();

返回发生绑定和取消绑定的对象的名字。

2 、 getSession

public HttpSession getSession();

返回发生绑定和取消绑定的 session 的名字。

HttpSessionBindingListener 接口

定义 \

public interface HttpSessionBindingListener

这个对象被加入到 HTTP 的 session 中,执行这个接口会通告有没有什么对象被绑定到这个 HTTP session 中或被从这个 HTTP session 中取消绑定。

方法

1 、 valueBound

public void valueBound(HttpSessionBindingEvent event);

当一个对象被绑定到 session 中,调用此方法。 HttpSession.putValue 方法被调用时, Servlet 引擎应该调用此方法。

2 、 valueUnbound

public void valueUnbound(HttpSessionBindingEvent event);

当一个对象被从 session 中取消绑定,调用此方法。 HttpSession.removeValue 方法被调用时, Servlet 引擎应该调用此方法。

Session 的事件处理机制与 swing 事件处理机制不同。 Swing 采用注册机制,而 session 没有;当任一 session 发生绑定或其他事件时,都会触发 HttpSessionBindingEvent ,如果 servlet 容器中存在 HttpSessionBindingListener 的实现类,则会将事件作为参数传送给 session 侦听器的实现类。在 HttpSessionBindingEvent 中可以通过 getsession 得到发生绑定和取消绑定的 session 的名字,而侦听器可以据此做更多处理。

因此,对 session 的事件侦听,只需实现 HttpSessionBindingListener 即可。

从 servlet2.3 增加了

HttpSessionEvent ( This is the class representing event notifications for changes to sessions within a web application )

HttpSessionActivationListener ( Objects that are bound to a session may listen to container events notifying them that sessions will be passivated and that session will be activated. )

HttpSessionAttributeListener ( This listener interface can be implemented in order to get notifications of changes to the attribute lists of sessions within this web application. )

分别执行不同的任务,处理基本相同。

三、 例子( zz )

捕获 Session 事件的意义:

1 、 记录网站的客户登录日志(登录,退出信息等)

2 、 统计在线人数

3 、 等等还有很多,呵呵,自己想吧 …… 总之挺重要的。

Session 代表客户的会话过程,客户登录时,往 Session 中传入一个对象,即可跟踪客户的会话。在 Servlet 中,传入 Session 的对象如果是一个实现 HttpSessionBindingListener 接口的对象(方便起见,此对象称为监听器),则在传入的时候(即调用 HttpSession 对象的 setAttribute 方法的时候)和移去的时候(即调用 HttpSession 对象的 removeAttribute 方法的时候或 Session Time out 的时候) Session 对象会自动调用监听器的 valueBound 和 valueUnbound 方法(这是 HttpSessionBindingListener 接口中的方法)。由此可知,登录日志也就不难实现了。

另外一个问题是,如何统计在线人数,这个问题跟实现登录日志稍微有点不同,统计在线人数(及其信息),就是统计现在有多少个 Session 实例存在,我们可以增加一个计数器(如果想存储更多的信息,可以用一个对象来做计数器,随后给出的实例中,简单起见,用一个整数变量作为计数器),通过在 valueBound 方法中给计数器加 1 , valueUnbound 方法中计数器减 1 ,即可实现在线人数的统计。当然,这里面要利用到 ServletContext 的全局特性。 ( 有关 ServletContext 的叙述请参考 Servlet 规范 ) ,新建一个监听器,并将其实例存入 ServletContext 的属性中,以保证此监听器实例的唯一性,当客户登录时,先判断 ServletContext 的这个属性是否为空,如果不为空,证明已经创建,直接将此属性取出放入 Session 中,计数器加 1 ;如果为空则创建一个新的监听器,并存入 ServletContext 的属性中。

举例说明:

实现一个监听器:

// SessionListener.java

import java.io.*;

import java.util.*;

import javax.servlet.http.*;

//监听登录的整个过程

public class SessionListener implements HttpSessionBindingListener

{

public String privateInfo=""; //生成监听器的初始化参数字符串

private String logString=""; //日志记录字符串

private int count=0; //登录人数计数器

public SessionListener(String info){

this.privateInfo=info;

}

public int getCount(){

return count;

}

public void valueBound(HttpSessionBindingEvent event)

{

count++;

if (privateInfo.equals("count"))

{

return;

}

try{

Calendar calendar=new GregorianCalendar();

System.out.println("LOGIN:"+privateInfo+" TIME:"+calendar.getTime());

logString="\nLOGIN:"+privateInfo+" TIME:"+calendar.getTime()+"\n";

for(int i=1;i<1000;i++){

File file=new File("yeeyoo.log"+i);

if(!(file.exists()))

file.createNewFile(); //如果文件不存在,创建此文件

if(file.length()>1048576) //如果文件大于1M,重新创建一个文件

continue;

FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true);

//以append方式打开创建文件

foo.write(logString.getBytes(),0,logString.length()); //写入日志字符串

foo.close();

break;//退出

}

}catch(FileNotFoundException e){}

catch(IOException e){}

}

public void valueUnbound(HttpSessionBindingEvent event)

{

count--;

if (privateInfo.equals("count"))

{

return;

}

try{

Calendar calendar=new GregorianCalendar();

System.out.println("LOGOUT:"+privateInfo+" TIME:"+calendar.getTime());

logString="\nLOGOUT:"+privateInfo+" TIME:"+calendar.getTime()+"\n";

for(int i=1;i<1000;i++){

File file=new File("yeeyoo.log"+i);

if(!(file.exists()))

file.createNewFile(); //如果文件不存在,创建此文件

if(file.length()>1048576) //如果文件大于1M,重新创建一个文件

continue;

FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true);

//以append方式打开创建文件

foo.write(logString.getBytes(),0,logString.length()); //写入日志字符串

foo.close();

break;//退出

}

}catch(FileNotFoundException e){}

catch(IOException e){}

}

}

登录日志的实现:

下面再来看看我们的登录 Servlet 中使用这个监听器的部分源代码:

……

HttpSession session = req.getSession (true);

……

//////////////////////////////////////////////////////////////////

SessionListener sessionListener=

new SessionListener("IP:"+req.getRemoteAddr());

//对于每一个会话过程均启动一个监听器

session.setAttribute("listener",sessionListener);

//将监听器植入HttpSession,这将激发监听器调用valueBound方法,

//从而记录日志文件。

//////////////////////////////////////////////////////////////////

当系统退出登录时,只需简单地调用 session.removeAttribute(“listener”);

即可自动调用监听器的 valueUnbound 方法。或者,当 Session Time Out 的时候也会调用此方法。

登录人数的统计:

ServletContext session1=getServletConfig().getServletContext();

//取得ServletContext对象实例

if((SessionListener)session1.getAttribute("listener1")==null)

{

SessionListener sessionListener1=new SessionListener("count");

//只设置一次,不同于上面日志文件的记录每次会话均设置。

//即当第一个客户连接到服务器时启动一个全局变量,

//此后所有的客户将使用相同的上下文。

session1.setAttribute("listener1",sessionListener1);

//将监听器对象设置成ServletContext的属性,具有全局范围有效性,

//即所有的客户均可以取得它的实例。

}

session.setAttribute("listener1",(SessionListener)session1.

getAttribute("listener1"));

//取出此全局对象,并且将此对象绑定到某个会话中,

//此举将促使监听器调用valueBound,计数器加一。

在此后的程序中随时可以用以下代码取得当前的登录人数:

((SessionListener)session.getAttribute("listener1")).getCount()

getCount() 是监听器的一个方法,即取得当前计数器的值也就是登录人数了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有