J2EE使用session监听实现在线用户明细及数量统计

来源:互联网 发布:java生成短信验证码 编辑:程序博客网 时间:2024/06/09 23:49

/*************************************************************/ 
/*
wallimn原创文章,欢迎转载,转载请保留本文信息。
博客:http://blog.csdn.net/wallimn    邮件:wallimn@sohu.com
*/
/*************************************************************/ 

  思路很简单,但与网上多数文章有所不同。我使用两个监听器,通过HttpSessionListener监听用户退出事件,通过HttpSessionAttributeListener监听用户登录事件。一般来讲,用户登录,都是向session中写入一个登录用户名。因此,可以通过监听session属性的变化,得到用户登录的情况。监听器配制方法,就是在web.xml加入如下代码: 
 <listener>
  <listener-class>com.wallimn.onlinestat.SessionListener</listener-class>
 </listener>

  使用工厂模式来设计,定义一个保存用户登录信息的接口(IStatStore),以便可以通过多种机制保存用户登录信息,如内存(MemStat)或数据库(JdbcStat)。定义一个类厂(StoreFactory),来实现保存机制的切换。

  注:我在代码中,没有完成JdbcStat这个类,若哪位用我的方法,写了这个类,最好能通过邮件发给我。谢谢。

  以上是一些设计思想的简单介绍,下面把几个程序贴一下。

SessionListener.java

/**
 * 文件:SessionListener.java<br/>
 * 功能:<br/>
 * 编码:wallimn(Email: wallimn@sohu.com  QQ: 54871876)<br/>
 * 版本:V1.0<br/>
 * 时间:2008-3-25<br/>
 * 备注:此代码欢迎讨论,转载请保留以上信息。
 
*/

package com.wallimn.onlinestat;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * session监听器,通过监听器来实现在线用户统计功能的类<br/>
 * 
 * 
@version : V1.0<br/>
 * 
@author : wallimn(Email: wallimn@sohu.com QQ: 54871876)<br/>
 * @date : 2008-3-25 上午09:41:11<br/>
 
*/

public class SessionListener implements HttpSessionListener,
        HttpSessionAttributeListener 
{
    
/**
     * 这个值应该根据不同的应用,改成不同的值
     
*/

    
private static final String LOGIN = "loginusername";

    
/**
     * 功能描述: 编码时间:2008-3-25 上午09:41:11 参数及返回值:
     * 
     * 
@param arg0
     * 
@see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent)
     
*/

    
public void sessionCreated(HttpSessionEvent se) {
        
// 时间: 2008-3-25 上午09:41:11
        System.out.println("Session创建:"+se.getSession().getId());
    }


    
/**
     * 功能描述:session销毁监控,销毁时注销用户 编码时间:2008-3-25 上午09:41:11 参数及返回值:
     * 
     * 
@param arg0
     * 
@see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent)
     
*/

    
public void sessionDestroyed(HttpSessionEvent se) {
        
// 时间: 2008-3-25 上午09:41:11
        String name = (String) se.getSession().getAttribute(LOGIN);
        System.out.println(
"有人登出:"+name);
        
if (name != null{
            StoreFactory.getStore().logoff(name);
        }

    }


    
/**
     * 
     * 功能描述:监控用户登录。有登录的,记录其状态。
     * 编码时间:2008-4-3  上午10:58:36
     * 参数及返回值:
     *  
@param event
     *  
@see javax.servlet.http.HttpSessionAttributeListener#attributeAdded(javax.servlet.http.HttpSessionBindingEvent)
     
*/

    
public void attributeAdded(HttpSessionBindingEvent event) {
        
// 时间: 2008-3-25 上午09:55:42
        String name = event.getName();
        
if (LOGIN.equals(name)) {
            StoreFactory.getStore().login((String) event.getValue());
            System.out.println(
"有人登录:"+event.getValue());
        }

    }


    
public void attributeRemoved(HttpSessionBindingEvent event) {
        
// 时间: 2008-3-25 上午09:55:42
    }


    
public void attributeReplaced(HttpSessionBindingEvent event) {
        
// 时间: 2008-3-25 上午09:55:42
    }


}

 接口:IStatStore.java 

package com.wallimn.onlinestat;
import java.util.List;
/**
 * 在线人数统计的接口,可以使用多种方式实现,如:内存、数据库等,只要实现这个接口就可以了。
 *<br/>
 * 
@version      :  V1.0<br/>
 * 
@author       : wallimn(Email: wallimn@sohu.com  QQ: 54871876)<br/>
 * @date           : 2008-4-4 下午02:01:07<br/>
 
*/

public interface IStatStore {
    
/**
     * 记录登录状态
     *<br/>
     *编码:wallimn     时间:2008-4-3  上午10:08:05<br/>
     *参数及返回值:<br/>
     *  
@param username
     
*/

    
public void login(String username);
    
/**
     * 取消登录状态
     *<br/>
     *编码:wallimn     时间:2008-4-3  上午10:08:17<br/>
     *参数及返回值:<br/>
     *  
@param username
     
*/

    
public void logoff(String username);
    
    
/**
     * 返回登录用户及信息。
     *<br/>
     *编码:wallimn     时间:2008-4-3  上午10:20:08<br/>
     *参数及返回值:<br/>
     *  
@return 链表里的对象是个数组,数组包含两个元素,0:用户名,1:登录时间。这样是为了便于为jstl标签处理
     
*/

    
public List getUsers();
    
    
/**
     * 在线用户数量
     *<br/>
     *编码:wallimn     时间:2008-4-4  下午01:52:55<br/>
     *参数及返回值:<br/>
     *  
@return
     
*/

    
public int getCount();
}

 

MemStat.java

package com.wallimn.onlinestat;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * 依托内存实现在线用户统计功能。适合于在线用户数量较少的情况。
 *<br/>
 * 
@version      :  V1.0<br/>
 * 
@author       : wallimn(Email: wallimn@sohu.com  QQ: 54871876)<br/>
 * @date           : 2008-4-4 下午01:53:36<br/>
 
*/

public class MemStat implements IStatStore {

    
private static Map userMap=null;
    
static {
        userMap 
= new HashMap();
    }


    
public void login(String username) {
        
//时间: 2008-4-3 上午10:09:13
        userMap.put(username, new Date());//如果存在,会覆盖已有的值
    }


    
public void logoff(String username) {
        
//时间: 2008-4-3 上午10:09:13
        userMap.remove(username);
    }


    
public List getUsers() {
        
//时间: 2008-4-3 上午10:23:34
        List list = new LinkedList();
        String user 
= null;
        
for(Iterator it = userMap.keySet().iterator();it.hasNext();){
            user 
= (String) it.next();
            list.add(
new Object[]{user,userMap.get(user)});
        }

        
return list;
    }


    
public int getCount() {
        
//时间: 2008-4-4 下午01:53:25
        return userMap.size();
    }


}

类厂:StoreFactory.java

 

package com.wallimn.onlinestat;

public class StoreFactory {
    
/**
     * 返回实现IStatStore接口的某种对象。
     *<br/>
     *编码:wallimn     时间:2008-4-3  上午10:54:05<br/>
     *参数及返回值:<br/>
     *  
@return 实现IStatStore接口的某种对象
     
*/

    
public static IStatStore getStore(){
        
//这里应该设计成从配制文件中读取,暂时先这样写。
        
//如果想在系统中使用jdbc的方式来实现统计功能,则返回JdbcStat对象即可。
        return new MemStat();
    }

}

 

页面上使用方法示例:

 

<%@ page language="java" pageEncoding="GB18030" %>
<%@ page import="com.wallimn.onlinestat.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
    
String path = request.getContextPath();
    
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    request.setAttribute(
"stat",StoreFactory.getStore().getUsers());
%>
<%--2007-9-20--%>
<!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>
    
<base href="<%=basePath%>"/>    
    
<title>在线用户统计</title>    
    
<meta http-equiv="pragma" content="no-cache"/>
    
<meta http-equiv="cache-control" content="no-cache"/>
    
<meta http-equiv="expires" content="0"/>    
    
<meta http-equiv="keywords" content="wallimn"/>
    
<meta http-equiv="description" content="在线用户显示,wallimn,2008年4月"/>
    
<style >
        h1
{
            text-align
:center;
            font-size
:18px;
            margin-top
:10px;
            margin-bottom
:10px;
        
}

        table
{
            border-collapse
:collapse;
            font-size
:12px;
        
}

        table,td,th
{
            border
:1px solid #EAEAEA;
        
}

        th
{
            height
:28px;
        
}

        td
{
            height
:24px;
            padding-left
:1em;
        
}

    
</style>
    
<script type="text/javascript">
    
</script>
  
</head>  
  
<body>
      
<h1>登录用户列表</h1>
      
<table width="80%" align="center">
               
<tr>
                  
<th>用户</th><th>登录时间</th>
              
</tr>
          
<c:forEach items="${stat}" var="item">
              
<tr>
                  
<td>${item[0]}</td><td>${item[1]}</td>
              
</tr>
          
</c:forEach>
      
</table>
 
</body>
 
</html>

/*************************************************************/ 
/*
wallimn原创文章,欢迎转载,转载请保留本文信息。
博客:http://blog.csdn.net/wallimn    邮件:wallimn@sohu.com
*/
/*************************************************************/ 

原创粉丝点击