HttpSessionListener与HttpSessionAttributeListener应用实例教程。使用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
- @WebListener
- public class OnlineListener
- implements HttpSessionListener
- {
- //当用户与服务器之间开始session时触发该方法
- public void sessionCreated(HttpSessionEvent se)
- {
- HttpSession sesession = se.getSession();
- ServletContext application = session.getServletContext();
- //获取session ID
- String sessionsessionId = session.getId();
- //如果是一次新的会话
- if (session.isNew())
- {
- 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
- <%@ page contentType=”text/html; charset=GBK”
language=”java” errorPage=”" %> - <%@ page import=”java.util.*” %>
- <!DOCTYPE html PUBLIC ”-//W3C//DTD XHTML 1.0 Transitional//EN”
- ”http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
- <html xmlns=”http://www.w3.org/1999/xhtml”>
- <head>
- <title> 用户在线信息 </title>
- </head>
- <body>
- 在线用户:
- <table width=”400″ border=”1″>
- <%
- 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
- @WebListener
- public class RequestListener
- implements ServletRequestListener
- {
- //当用户请求到达、被初始化时触发该方法
- public void requestInitialized(ServletRequestEvent sre)
- {
- HttpServletRequest request =
(HttpServletRequest)sre.getServletRequest(); - HttpSession session = request.getSession();
- //获取session ID
- String sessionsessionId = session.getId();
- //获取访问的IP和正在访问的页面
- String ip = request.getRemoteAddr();
- String page = request.getRequestURI();
- String user = (String)session.getAttribute(“user”);
- //未登录用户当游客处理
- user = (user == null) ? ”游客” : user;
- try
- {
- DbDao dd = new DbDao(“com.mysql.jdbc.Driver”
- , ”jdbc:mysql://localhost:3306/online_inf”
上面的程序中粗体字代码控制用户会话是新的session,还是已有的session,新的session将插入数据表;旧的session将更新数据表中对应的记录。
接下来定义一个ServletContextListener,它负责启动一条后台线程,这条后台线程将会定期检查在线记录,并删除那些长时间没有重新请求过的记录。该Listerner代码如下。
程序清单:codes\02\2.13\ online\WEB-INF\src\lee\OnlineListener.java
- @WebListener
- public class OnlineListener
- implements ServletContextListener
- {
- //超过该时间(10分钟)没有访问本站即认为用户已经离线
- public final int MAX_MILLIS = 10 * 60 * 1000;
- //应用启动时触发该方法
- public void contextInitialized(ServletContextEvent sce)
- {
- //每5秒检查一次
- new javax.swing.Timer(1000 * 5 , new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- try
- {
- DbDao dd = new DbDao(“com.mysql.jdbc.Driver”
- , ”jdbc:mysql://localhost:3306/online_inf”
- , ”root”
- , ”32147″);
- ResultSet rs = dd.query
(“select * from online_inf” , false); - StringBuffer beRemove = new StringBuffer(“(“);
- while(rs.next())
- {
- //如果距离上次访问时间超过了指定时间
- if ((System.currentTimeMillis() - rs.getLong(5))
- > MAX_MILLIS)
- {
- //将需要被删除的session ID添加进来
- beRemove.append(“‘”);
- beRemove.append(rs.getString(1));
- beRemove.append(“‘ , ”);
- }
- }
- //有需要删除的记录
- if (beRemove.length() > 3)
- {
- beRemove.setLength(beRemove.length() - 3);
- beRemove.append(“)”);
- //删除所有”超过指定时间未重新请求的记录”
- dd.modify(“delete
from online_inf where session_id in ” - + beRemove.toString());
- }
- dd.closeConn();
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- }).start();
- }
- public void contextDestroyed(ServletContextEvent sce)
使用ServletRequestListener和ServletRequestAttributeListener
ServletRequestListener用于监听用户请求的到达,实现该接口的监听器需要实现如下两个方法。
requestInitialized(ServletRequestEvent sre):用户请求到底、被初始化时触发该方法。
requestDestroyed(ServletRequestEvent sre):用户请求结束、被销毁时触发该方法。
ServletRequestAttributeListener则用于监听ServletRequest(request)范围内属性的变化,实现该接口的监听器需要实现attributeAdded、attributeRemoved、attributeReplaced三个方法。由此可见,ServletRequestAttributeListener与ServletContextAttributeListener的作用相似,都用于监听属性的改变,只是ServletRequestAttributeListener监听request范围内属性的改变,而ServletContextAttributeListener监听的是application范围内属性的改变。
需要指出的是,应用程序完全可以采用一个监听器类来监听多种事件,只要让该监听器实现类同时实现多个监听器接口即可,如以下代码所示。
程序清单:codes\02\2.13\listenerTest\WEB-INF\src\lee\RequestListener.java
- @WebListener
- public class RequestListener
- implements ServletRequestListener ,
ServletRequestAttributeListener - {
- //当用户请求到达、被初始化时触发该方法
- public void requestInitialized(ServletRequestEvent sre)
- {
- HttpServletRequest request =
(HttpServletRequest)sre.getServletRequest(); - System.out.println(“—-发向” + request.getRequestURI()
- + ”请求被初始化—-”);
- }
- //当用户请求结束、被销毁时触发该方法
- public void requestDestroyed(ServletRequestEvent sre)
- {
- HttpServletRequest request =
(HttpServletRequest)sre.getServletRequest(); - System.out.println(“—-发向” + request.getRequestURI()
- + ”请求被销毁—-”);
- }
- //当程序向request范围添加属性时触发该方法
- public void attributeAdded(ServletRequestAttributeEvent event)
- {
- ServletRequest request = event.getServletRequest();
- //获取添加的属性名和属性值
- String name = event.getName();
- Object value = event.getValue();
- System.out.println(request + ”范围内添加了名为”
- + name + ”,值为” + value + ”的属性!”);
- }
- //当程序从request范围删除属性时触发该方法
- public void attributeRemoved(ServletRequestAttributeEvent event)
- {
- ServletRequest request = event.getServletRequest();
- //获取被删除的属性名和属性值
- String name = event.getName();
- Object value = event.getValue();
- System.out.println(request + ”范围内名为”
- + name + ”,值为” + value + ”的属性被删除了!”);
- }
- //当request范围的属性被替换时触发该方法
- public void attributeReplaced(ServletRequestAttributeEvent event)
- {
- ServletRequest request = event.getServletRequest();
- //获取被替换的属性名和属性值
上面的监听器实现类同时实现了ServletRequestListener接口和ServletRequestAttributerListener接口,因此它既可以监听用户请求的初始化和销毁,也可监听request范围内属性的变化。
由于实现了ServletRequestListener接口的监听器可以非常方便地监听到每次请求的创建、销毁,因此Web应用可通过实现该接口的监听器来监听访问该应用的每个请求,从而实现系统日志。