使用HttpSessionListener和HttpSessionAttributeListener(1)

39 篇文章 0 订阅
使用HttpSessionListener和HttpSessionAttributeListener(1)

HttpSessionListener用于监听用户session的创建和销毁,实现该接口的监听器需要实现如下两个方法。

sessionCreated(HttpSessionEvent se):用户与服务器的会话开始、创建时时触发该方法。

sessionDestroyed(HttpSessionEvent se):用户与服务器的会话断开、销毁时触发该方法。

HttpSessionAttributeListener则用于监听HttpSession(session)范围内属性的变化,实现该接口的监听器需要实现attributeAdded、attributeRemoved、attributeReplaced三个方法。由此可见,HttpSessionAttributeListener与ServletContextAttributeListener的作用相似,都用于监听属性的改变,只是HttpSessionAttributeListener监听session范围内属性的改变,而ServletContextAttributeListener监听的是application范围内属性的改变。

http://book.51cto.com/art/201104/253576.htm

实现HttpSessionListener接口的监听器可以监听每个用户会话的开始和断开,因此应用可以通过该监听器监听系统的在线用户。

下面是该监听器的实现类。

程序清单:codes\02\2.13\listenerTest\WEB-INF\src\lee\OnlineListener.java

    1. @WebListener  
    2. public class OnlineListener  
    3.     implements HttpSessionListener  
    4. {  
    5.     //当用户与服务器之间开始session时触发该方法  
    6.     public void sessionCreated(HttpSessionEvent se)  
    7.     {  
    8.         HttpSession sesession = se.getSession();  
    9.         ServletContext application = session.getServletContext();  
    10.         //获取session ID  
    11.         String sessionsessionId = session.getId();  
    12.         //如果是一次新的会话  
    13.         if (session.isNew())  
    14.         {  
    15.             String user = (String)session.getAttribute("user");

上面的监听器实现类实现了HttpSessionListener接口,该监听器可用于监听用户与服务器之间session的开始、关闭,当用户与服务器之间的session开始时,如果该session是一次新的session,程序就将当前用户的session ID、用户名存入application范围的Map中;当用户与服务器之间的session关闭时,程序从application范围的Map中删除该用户的信息。通过上面的方式,application范围内的Map就记录了当前应用的所有在线用户。

显示在线用户的页面代码很简单,只要迭代输出application范围的Map即可,如以下代码所示。

程序清单:codes\02\2.13\listenerTest\online.jsp

  1. <%@ page contentType="text/html; charset=GBK" 
    language="java" errorPage="" %> 
  2. <%@ page import="java.util.*" %> 
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
  4.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
  5. <html xmlns="http://www.w3.org/1999/xhtml"> 
  6. <head> 
  7.     <title> 用户在线信息 </title> 
  8. </head> 
  9. <body> 
  10. 在线用户:  
  11. <table width="400" border="1"> 
  12. <%  
  13. Map<String , String> online = (Map<String , String>)application  

2.13.5  使用HttpSessionListener和HttpSessionAttributeListener(2)

笔者在本机启动三个不同的浏览器来模拟三个用户访问该应用,访问online.jsp页面将可看到如图2.42所示页面。

需要指出的是:采用HttpSessionListener监听用户在线信息比较"粗糙",只能监听到有多少人在线,每个用户的session ID等基本信息。如果应用需要监听到每个用户停留在哪个页面、本次在线的停留时间、用户的访问IP等信息,则应该考虑定时检查HttpServletRequest来实现。

通过检查HttpServletRequest的做法可以更精确地监控在线用户的状态,这种做法的思路是:

定义一个ServletRequestListener,这个监听器负责监听每个用户请求,当用户请求到达时,系统将用户请求的session ID、用户名、用户IP、正在访问的资源、访问时间记录下来。

启动一条后台线程,这条后台线程每隔一段时间检查上面的每条在线记录,如果某条在线记录的访问时间与当前时间相差超过了指定值,将这条在线记录删除即可。这条后台线程应随着Web应用的启动而启动,可考虑使用ServletContextListener来完成。

下面先定义一个ServletRequestListener,它负责监听每次用户请求:每次用户请求到达时,如果是新的用户会话,将相关信息插入数据表;如果是老的用户会话,则更新数据表中已有的在线记录。

程序清单:codes\02\2.13\ online\WEB-INF\src\lee\RequestListener.java

  1. @WebListener  
  2. public class RequestListener  
  3.     implements ServletRequestListener  
  4. {  
  5.     //当用户请求到达、被初始化时触发该方法  
  6.     public void requestInitialized(ServletRequestEvent sre)  
  7.     {  
  8.         HttpServletRequest request =
    (HttpServletRequest)sre.getServletRequest();  
  9.         HttpSession session = request.getSession();  
  10.         //获取session ID  
  11.         String sessionsessionId = session.getId();  
  12.         //获取访问的IP和正在访问的页面  
  13.         String ip = request.getRemoteAddr();  
  14.         String page = request.getRequestURI();  
  15.         String user = (String)session.getAttribute("user");  
  16.         //未登录用户当游客处理  
  17.         user = (user == null) ? "游客" : user;  
  18.         try  
  19.         {  
  20.             DbDao dd = new DbDao("com.mysql.jdbc.Driver"  
  21.                 , "jdbc:mysql://localhost:3306/online_inf"

上面的程序中粗体字代码控制用户会话是新的session,还是已有的session,新的session将插入数据表;旧的session将更新数据表中对应的记录。

接下来定义一个ServletContextListener,它负责启动一条后台线程,这条后台线程将会定期检查在线记录,并删除那些长时间没有重新请求过的记录。该Listerner代码如下。

程序清单:codes\02\2.13\ online\WEB-INF\src\lee\OnlineListener.java

  1. @WebListener  
  2. public class OnlineListener  
  3.     implements ServletContextListener  
  4. {  
  5.     //超过该时间(10分钟)没有访问本站即认为用户已经离线  
  6.     public final int MAX_MILLIS = 10 * 60 * 1000;  
  7.     //应用启动时触发该方法  
  8.     public void contextInitialized(ServletContextEvent sce)  
  9.     {  
  10.         //每5秒检查一次  
  11.         new javax.swing.Timer(1000 * 5 , new ActionListener()  
  12.         {  
  13.             public void actionPerformed(ActionEvent e)  
  14.             {  
  15.                 try  
  16.                 {  
  17.                     DbDao dd = new DbDao("com.mysql.jdbc.Driver"  
  18.                         , "jdbc:mysql://localhost:3306/online_inf"  
  19.                         , "root"  
  20.                         , "32147");  
  21.                     ResultSet rs = dd.query
    ("select * from online_inf" , false);  
  22.                     StringBuffer beRemove = new StringBuffer("(");  
  23.                     while(rs.next())  
  24.                     {  
  25.                         //如果距离上次访问时间超过了指定时间  
  26.                         if ((System.currentTimeMillis() - rs.getLong(5))  
  27.                             > MAX_MILLIS)  
  28.                         {  
  29.                             //将需要被删除的session ID添加进来  
  30.                             beRemove.append("'");  
  31.                             beRemove.append(rs.getString(1));  
  32.                             beRemove.append("' , ");  
  33.                         }  
  34.                     }  
  35.                     //有需要删除的记录  
  36.                     if (beRemove.length() > 3)  
  37.                     {  
  38.                         beRemove.setLength(beRemove.length() - 3);  
  39.                         beRemove.append(")");  
  40.                         //删除所有"超过指定时间未重新请求的记录"  
  41.                         dd.modify("delete 
    from online_inf where session_id in "  
  42.                             + beRemove.toString());  
  43.                     }  
  44.                     dd.closeConn();  
  45.                 }  
  46.                 catch (Exception ex)  
  47.                 {  
  48.                     ex.printStackTrace();  
  49.                 }  
  50.             }  
  51.         }).start();  
  52.     }  
  53.     public void contextDestroyed(ServletContextEvent sce)  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值