在线用户统计(一)

好久之前看过下在线人数统计的问题,现在重新整理了一下,把自己写的一些例子发出来和大家分享,希望大家也提出一些想法或者例子,一起研究出最好的方案=^^=

在写文章之前先介绍一个HttpSessionBindingListener这个监听器,用来监听自己什么时候增加到会话中,或者从会话删除。实现HttpSessionBindingListener这个接口要实现2个方法:valueBound(当我知道我在一个会话中时要运行的代码),valueUnbound(当我知道已经不在一个会话时要运行的代码)

代码如下:
[color=red]//实现一个HttpSessionBindingListener监听器[/color]-----OnLineUser.java

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.apache.log4j.Logger;
import java.util.*;

public class OnLineUser implements HttpSessionBindingListener {

static Logger logger = Logger.getLogger(OnLineUser.class.getName());

// 创建一个静态变量来保存在线用户
private static Vector<String> users = new Vector<String>();

//返回当前在线人数
public int getCount() {

return users.size();
}

//判断用户是否重复登陆
public boolean existUser(String userName) {

boolean existUser = false; // 用户不存在
for (int i = 0; i < users.size(); i++) {
if (userName.equals((String) users.get(i))) {
existUser = true; // 用户已存在
break;
}
}
return existUser;
}

//从统计中删除用户
public boolean deleteUser(String userName) {
OnLineUser.logger.info("=============移除用户============");
boolean flag = false;
for (int i = 0; i < users.size(); i++) {
if (userName.equals((String) users.get(i))) {
users.remove(i);
flag = true;
break;
}
}
return flag;
}

public void valueBound(HttpSessionBindingEvent e) {
//每当OnLineUser这个实例被绑定到会话里面,就从统计中增加一个在线用户
users.add(e.getName());

OnLineUser.logger.info(e.getName() + "\t登入到系统\t" + (new Date()));

for (int i = 0; i < users.size(); i++) {
OnLineUser.logger.info("第"+ (i+1) + "个在线用户:" + users.get(i));
}
OnLineUser.logger.info("在线用户数为:" + getCount() + "人");


}

public void valueUnbound(HttpSessionBindingEvent e) {
String userName = e.getName();
//每当OnLineUser的实例与Session解除绑定时,就从统计中移除改在线用户
boolean flag = deleteUser(userName);
if (flag == true) {
OnLineUser.logger.info(userName + "\t退出系统\t" + (new Date()));
OnLineUser.logger.info("\t在线用户数为:" + getCount());
}
}

public static Vector getUsers() {
return users;
}

}

[color=red]//敲完Listener的代码需要在DD中(web.xml)文件配置一下,只需要在web.xml增加下面这段即可[/color]
<!-- 配置listener -->
<listener>
<listener-class>com.listener.OnLineUser</listener-class>
</listener>
<!--注意路径不一定是com.listener.OnLineUser,需按照你自己的实际路径 -->


[color=red]//模拟一个业务逻辑组件的实现[/color]-----Service.java
public class Service {
private static Service service;

private String[] user = {"Jam","Rjx","Wjm","Jason"};
private String[] pass = {"123","123","123","123"};

//单例模式的私有构造函数
private Service(){

}

//返回Service实例
public static Service getInstance(){
if(service == null){
synchronized(Service.class){
if(service == null){
service = new Service();
}
}
}
return service;
}

//本来是去数据库检查帐号密码是否一致,这里把情况简单化
public boolean checkUser(String userName,String password){

for(int i=0;i<user.length;i++){
if(userName.equals(user[i]) && password.equals(pass[i])){
return true;
}
}
return false;
}
}



[color=red]//控制层(表示层)的实现,当用户提交表单时就会来到这个Servlet[/color]-----LoginServlet.java
public class LoginServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

doPost(request,response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String userName = request.getParameter("userName");
String password = request.getParameter("password");

HttpSession session = request.getSession();

//调用service组件的checkUser方法
boolean flag = Service.getInstance().checkUser(userName, password);
if(flag == true){
OnLineUser onLineUser = new OnLineUser();
if(onLineUser.existUser(userName)){
OnLineUser.logger.info(userName+"重复登陆");

}
else{

session.setAttribute(userName, onLineUser);
//设置session的失效时间(秒为单位)
session.setMaxInactiveInterval(10);
}
}
//跳转(请求分派)到onLineResult.jsp页面
request.getRequestDispatcher("onLineResult.jsp").forward(request, response);
}

}

//省略了Servlet在DD中的配置文件



[color=red]//jsp客户端代码如下,代码比较简单,就不左解释了哈:)[/color]-----onLineLogin.jsp
<html>
<head>
<title>统计在线人数登陆页面</title>
</head>

<body>

<form action="LoginServlet" method="post">
<table border="1">
<tr><td colspan="2" align="center"><font color="red">在线人数统计调查表</font></td></tr>
<tr><td>请输入名字:</td><td><input type="text" name="userName"/></td></tr>
<tr><td>请输入密码:</td><td><input type="text" name="password"/></td></tr>
<tr align="center"><td colspan="2"><input type="submit" value="提交"></td></tr>
</table>
</form>
</body>
</html>



[color=red]//访问完控制层跳转的页面,显示在线人数[/color]-----onLineResult.jsp

<html>
<head>
<title>统计在线人数结果</title>
</head>
<body>
现在的在线人数是:<%=OnLineUser.getUsers().size() %>
</body>
</html>



[color=red]小结:[/color]在测试的过程中,我发现就算我设置session的过期时间为1秒,也要等几十秒,才会执行valueUnbound这个方法,不知道是session过期有延迟,还是监听器本身有延迟,暂时没什么头绪。至于这个做法,其中一个缺点是,当在线用户人数多的时候,后台会产生大量的OnLineUser的实例。欢迎大家提出更好的建议和方法:)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值