使用Listener统计在线账户信息

 统计在线账户信息的开发过程大致分为以下几步:

一、开发RequestListener类,并实现ServletRequestListener接口,用于监听每个用户的请求信息。

二、开发OnlineListener类,并实现ServletRequestContext接口,用于定期检查在线记录,并删除长期没有请求的记录。该类是一个后台线程,随着程序的启动而启动

三、DAO层

四、web.xml文件的配置

五、开发JSP,显示在线用户信息

 

下面开始程序的开发:

一、开发RequestListener类,并实现ServletRequestListener接口,当用户请求到达时,会调用ServletRequestListener接口的requestInitialized方法,当用户断开请求时,会调用ServletRequestListener接口的requestDestroyed方法。RequestListener类主要用于记录访问用户的sessionId,用户状态,用户IP,访问的时间及请求的页面,代码如下:

public class RequestListener implements ServletRequestListener {
 // 当用户请求到达,被初始化时触发该方法
 public void requestInitialized(ServletRequestEvent sre) {
  HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
  HttpSession session = request.getSession();
  // 获得sessionId
  String sessionId = session.getId();
  // 访问的页面
  String page = request.getRequestURI();
  // 获得用户的IP
  String ip = request.getRemoteAddr();
  String user = (String) session.getAttribute("user");
  user = (user == null) ? "游客" : user;
  DbDao db = new DbDao("oracle.jdbc.OracleDriver", "jdbc:oracle:thin:@127.0.0.1:1521:ORCAL", "scott", "sa");
  try {
   // 这里的SQL语句写成select *,把要查询的字段列出来才可以,不然会出现"对只读结果集的无效操作updateString"的错误信息
   ResultSet rs = db.query("select session_id,username,user_ip,access_res,last_access from online_info where session_id=? ", true, sessionId);
   // 如果有记录,则更新,否则插入数据库
   if (rs.next()) {
    rs.updateString(4, page);
    rs.updateLong(5, System.currentTimeMillis());
    rs.updateRow();
    rs.close();
   } else {
    db.insert("insert into online_info values(?,?,?,?,?)", sessionId, user, ip, page, System.currentTimeMillis());
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 // 当用户退出被销毁时触发该方法
 public void requestDestroyed(ServletRequestEvent sre) {

 }

}

二、开发OnlineListener对象,实现ServletRequestContext接口,当应用程序开启时,会调用ServletRequestContext接口的contextInitialized方法,当应用程序关闭时,会调用ServletRequestContext接口的contextDestroyed方法。OnlineListener对象用于定期检查在线记录,并删除长期没有请求的记录。该类是一个后台线程,随着程序的启动而启动,代码如下:

public class OnlineListener implements ServletContextListener {
 public static final int MAX_MILLIS=1*60*1000;
 //程序起动时触发该方法
 public void contextInitialized(ServletContextEvent arg0) {
  new Timer(1000*5, new ActionListener(){
   public void actionPerformed(ActionEvent e) {
    try {
     DbDao dd=new DbDao("oracle.jdbc.OracleDriver","jdbc:oracle:thin:@127.0.0.1:1521:ORCAL","scott","sa");
     ResultSet rs=dd.query("select * from online_info", false);
     StringBuilder beRemove=new StringBuilder("(");
     while(rs.next()){
      //如果当前距离上次访问时间超过了指定时间
      if((System.currentTimeMillis()-rs.getLong(5))>MAX_MILLIS){
       //将要被删除的SessionID添加进来
       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_info where session_id in "+beRemove.toString());
     }
     
     
    } catch (Exception e1) {
     // TODO Auto-generated catch block
     e1.printStackTrace();
    }
   }
   
  }).start();
 }
 //程序关闭时触发该方法
 public void contextDestroyed(ServletContextEvent arg0) {

 }

}

 

三、DAO层代码如下:

public class DbDao {
 private String driver;
 private String uri;
 private String userName;
 private String password;

//这里省略getter和setter方法

 private Connection con = null;
 private PreparedStatement pstmt = null;
 private ResultSet rs = null;

 public DbDao() {

 }

 public DbDao(String driver, String uri, String userName, String password) {
  this.driver = driver;
  this.uri = uri;
  this.userName = userName;
  this.password = password;
 }

 /**
  * @param sql
  *            sql语句
  * @param updatable
  *            是否可更新
  * @param args
  *            可变参数
  * @return ResultSet
  * @throws Exception
  */
 public ResultSet query(String sql, boolean updatable, Object... args) throws Exception {
  PreparedStatement pstmt = null;
  if (updatable) {
   // 创建可更新的prepareStatement
   // TYPE_SCROLL_SENSITIVE:生成的ResultSet对象可以定位信息,可向前向后访问,如果用户执行完后删除一条记录,那么也从ResultSet中删除
   // CONCUR_UPDATABLE:指定可以更新ResultSet
   pstmt = getCon().prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
  } else {
   pstmt = getCon().prepareStatement(sql);
  }
  for (int i = 0; i < args.length; i++) {
      pstmt.setObject(i + 1, args[i]);
  }
  rs = pstmt.executeQuery();
  return rs;
 }

 /**
  *
  * @param sql
  *            sql语句
  * @param args
  *            可变参数
  * @return boolean
  * @throws Exception
  */
 public boolean insert(String sql, Object... args) throws Exception {
  pstmt = getCon().prepareStatement(sql);
  for (int i = 0; i < args.length; i++) {
   pstmt.setObject(i + 1, args[i]);
  }
  if (pstmt.executeUpdate() != 1) {
   return false;
  }
  return true;
 }

 public Connection getCon() throws Exception {
  if (con == null) {
   Class.forName(driver);
   con = DriverManager.getConnection(uri, userName, password);
  }
  return con;
 }

 public void modify(String sql, Object... args) throws SQLException, Exception {
  pstmt = getCon().prepareStatement(sql);
  pstmt.executeUpdate();
 }

}

 

四、在web.xml文件中配置listener

<listener>
   <listener-class>listener.RequestListener</listener-class>
  </listener>
  <listener>
   <listener-class>listener.OnlineListener</listener-class>
  </listener>

 

五、JSP的开发,为了简单,这里直接在jsp中写Java代码了,代码如下:

<%@page contentType="text/html;charset=utf-8" errorPage="" %>
<%@page import="java.sql.*,listener.*" %>
<html>
 
 <head>
  <title>统计在线用户信息</title>
 </head>
 <body>
  <h2>当前在线用户信息</h2>
  <table style="border:solid 1px black; width:700px;">
   <tr><td>sessionId</td><td>用户类型</td><td>用户IP地址</td><td>请求页面</td></tr>
   <% DbDao dd=new DbDao("oracle.jdbc.OracleDriver","jdbc:oracle:thin:@127.0.0.1:1521:ORCAL","scott","sa");
   ResultSet rs=dd.query("select * from online_info",false);
   while(rs.next()){%>
    <tr style="border:solid 1px black;">
     <td><%=rs.getString(1) %></td>
     <td><%=rs.getString(2) %></td>
     <td><%=rs.getString(3) %></td>
     <td><%=rs.getString(4) %></td>
    </tr>
   <% }%>
  </table>
 </body>
</html>

到此,统计在线用户信息的代码就已经开发完了,只需在地址栏中直接访问JSP,就可以查看到在线用户的信息

注:此文章部分代码功能摘至《轻量级JavaEE企业应用实践》李刚 著

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值