Javaweb统计在线人数的小栗子

最近在学习Javaweb相关的内容(不黑不吹之前对web开发零基础),下面通过一个统计在线人数的小栗子讲讲Servlet监听器吧

开发环境 eclipse  tomcat 7

先说说这个小栗子的构思:

首先要考虑的就是通过什么方式能够统计在线人数?很容易想到可以通过session来统计在线人数为什么不是request呢?因为request在请求结束时即服务器返回资源时就被销毁了,也就是说request的作用域不足以用以统计在线人数。服务器在第一次接受一个用户请求时会给该用户分配一个sessionid在有效期结束后或是用户主动关闭浏览器一段时间后session会被销毁,所以用session来统计在线人数是合情合理的。

接下来问题来了,知道了统计在线人数和session相关那么应该如何操作呢?下面说说Servlet监听器。

Servlet监听器只要就是用来对Web应用进行监听和控制的,功能接近Java的GUI程序的监听器,可以监听由于Web应用程序状态改变而引起的Servlet容器产生的相应事件,然后作出处理。

Servlet监听器分为Servlet上下文监听器,Http会话监听器,Servlet请求监听器。

既然用到了Session那我们先来看看Session相关的监听器吧。查看Apache文档

HttpSessionListener接口有两个方法对应的是session被创建和被销毁时调用的。定义一个监听器类实现HttpSessionListener接口代码如下所示

 1 package com.xiaoysec;
 2
 3 import java.util.ArrayList;
 4
 5 import javax.servlet.annotation.WebListener;
 6 import javax.servlet.http.HttpSessionEvent;
 7 import javax.servlet.http.HttpSessionListener;
 8
 9 /**
10  * Application Lifecycle Listener implementation class MyHttpSessionListener
11  *
12  */
13
14 public class MyHttpSessionListener implements HttpSessionListener {
15     private int numberCount = 0;
16
17     /**
18      * Default constructor.
19      */
20     public MyHttpSessionListener() {
21         // TODO Auto-generated constructor stub
22     }
23
24     /**
25      * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
26      */
27     public void sessionCreated(HttpSessionEvent arg0) {
28         // TODO Auto-generated method stub
29         numberCount++;
30         arg0.getSession().getServletContext()
31                 .setAttribute("numberCount", numberCount);
32     }
33
34     /**
35      * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
36      */
37     public void sessionDestroyed(HttpSessionEvent arg0) {
38         // TODO Auto-generated method stub
39         numberCount--;
40         arg0.getSession().getServletContext()
41                 .setAttribute("numberCount", numberCount);
42         ArrayList<Userinfo> userlist = (ArrayList<Userinfo>) arg0.getSession()
43                 .getServletContext().getAttribute("userlist");
44         if (SessionUtil.getUsersessionid(userlist, arg0.getSession().getId()) != null) {
45             userlist.remove(SessionUtil.getUsersessionid(userlist, arg0
46                     .getSession().getId()));
47         }
48     }
49
50 }

在Session被创建时numberCount++,在被销毁时numberCount--。这样,一个简单的在线人数统计功能就实现了,接下来完善一下,如果想看到客户端的ip信息又该怎么办呢?首先还是思考如何获取用户信息,很容易想到可以通过request获取客户端的信息。

定义一个封装用户信息的Javabean,代码如下:

 1 package com.xiaoysec;
 2
 3 public class Userinfo {
 4     private String sessionid;
 5     private String ip;
 6     private String recenttime;
 7
 8     public String getSessionid() {
 9         return sessionid;
10     }
11
12     public void setSessionid(String sessionid) {
13         this.sessionid = sessionid;
14     }
15
16     public String getIp() {
17         return ip;
18     }
19
20     public void setIp(String ip) {
21         this.ip = ip;
22     }
23
24     public String getRecenttime() {
25         return recenttime;
26     }
27
28     public void setRecenttime(String recenttime) {
29         this.recenttime = recenttime;
30     }
31
32 }

定义一个类MyServletRquestListener实现ServletRequestListener接口,在该接口中定义了一个requestInitialized方法,在服务器端接收到客户端的请求时被调用,

代码如下:

 1 package com.xiaoysec;
 2
 3 import java.text.SimpleDateFormat;
 4 import java.util.ArrayList;
 5 import java.util.Date;
 6
 7 import javax.servlet.ServletRequestEvent;
 8 import javax.servlet.ServletRequestListener;
 9 import javax.servlet.annotation.WebListener;
10 import javax.servlet.http.HttpServletRequest;
11
12 public class MyServletRquestListener implements ServletRequestListener {
13     private ArrayList<Userinfo> userlist; // 在綫用戶的list
14
15     @Override
16     public void requestDestroyed(ServletRequestEvent arg0) {
17         // TODO Auto-generated method stub
18
19     }
20
21     /**
22      * 在初始化request的初始化中判斷是否存在user的信息(sessionid)如果不存在的話就保存在userlist中
23      */
24     @Override
25     public void requestInitialized(ServletRequestEvent arg0) {
26         userlist = (ArrayList<Userinfo>) arg0.getServletContext().getAttribute("userlist");
27         if(userlist==null)
28             userlist = new ArrayList<Userinfo>();
29         HttpServletRequest req = (HttpServletRequest) arg0.getServletRequest();
30         String sessionid = req.getSession().getId();
31         if (SessionUtil.getUsersessionid(userlist, sessionid) == null) {
32             Userinfo user = new Userinfo();
33             user.setIp(req.getRemoteAddr());
34             user.setSessionid(sessionid);
35             user.setRecenttime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
36                     .format(new Date()));
37             userlist.add(user);
38         }
39         arg0.getServletContext().setAttribute("userlist", userlist);
40     }
41
42 } 

接着写一个SessionUtil类实现了getUsersessionid方法,代码如下:

 1 package com.xiaoysec;
 2
 3 import java.util.ArrayList;
 4
 5 public class SessionUtil {
 6     public static Object getUsersessionid(ArrayList<Userinfo> userlist,String sessionid) {
 7          for(int i=0;i<userlist.size();i++){
 8               Userinfo info = userlist.get(i);
 9               if(userlist.get(i).getSessionid().equals(sessionid)) //表示当前的sessionid用户存在于用户list中不需要
10                   return info;
11          }
12         return null;
13     }
14
15 }

在getUsersessionid中参数为userlist和sessionid,通过一个循环判断sessionid所指的用户是否在userlist中如果在的话就返回用户信息info,如果不在的话就返回null并在MyServletRquestListener的31行处添加进userlist。

最后是界面jsp展示

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <%@  page import="java.util.*"%>
 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 5 <html>
 6 <head>
 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 8 <title>Insert title here</title>
 9 </head>
10 <body>
11     当前用户在线人数<%= application.getAttribute("numberCount") %><br/>
12     <%
13         ArrayList<com.xiaoysec.Userinfo> userlist = (ArrayList<com.xiaoysec.Userinfo>)request
14                 .getServletContext().getAttribute("userlist");
15     if(userlist!=null){
16         for (int i=0;i<userlist.size();i++) {
17             com.xiaoysec.Userinfo info = userlist.get(i);
18     %>
19     ip:<%=info.getIp()%><br />
20     recentTime:<%=info.getRecenttime()%><br/>
21     sessionid:<%=info.getSessionid()%><br/>
22     <%
23         }}
24     %>
25 </body>
26 </html>

总结:通过这个小栗子只是对Servlet监听器有一个小小的了解,还是需要多看源码,理解过程,多代码,多思考,多总结。

时间: 2024-08-01 22:40:58

Javaweb统计在线人数的小栗子的相关文章

asp.net MVC 统计在线人数功能实现

今天开发一个设计一个统计在线人数的统计.实现方式是在MVC 中,用户次执行一个Action请求完成后,向数据表中插入一条用户心跳记录,统计在线人数则是根据该记录,30分钟内有记录的用户则为在线状态. 首先设计表心跳记录表结构MOdel 接下来添加 CheckACAttribute 类继承 ActionFilterAttribute基类,并在FilterConfig类中注册. public class FilterConfig    {        public static void Regi

ASP.NET中利用Application和Session统计在线人数、历史访问量

先来简单说一下ASP.NET中的Application和Session 下图是我们非常熟悉的Web应用程序的结构: 在这张图中,Web服务器中运行的Web应用程序就是我们所说的Application,每个客户端与Web服务器之间建立的连接就可以看做是一个Session.比如现在服务器端运行的是一个论坛系统,那么现在这个正运行在服务器端的论坛系统的软件就可以看做Application,而每个在线的用户与之建立的连接就相当于一个Session. 那么很容易就会理解,Application是共享的,相

【ASP.NET】——统计在线人数、历史访问人数

北大青鸟的视频中讲了很多很实用的例子,这是其中一个,在实现的过程中,遇到一些问题,但也都在老师的指导下和通过查阅资料解决了,感觉收获颇丰. 在做这个例子的时候发现:ASP.NET的Application和Session统计在线人数和历史访问人数时不准.明明已经关闭浏览器了,在线人数却没少,重新登录,历史人数也没增加.难道是我做错了,No.原因在这里. 首先,先简单说一下Application和Session. Application:应用程序类的对象.类比到这个程序,服务器端的统计人数程序就相当

JavaWeb图表插件的小研究

背景 最近的一个项目中,对数据的统计分析有很大的要求,这就要求有一款很强大的报表.图表插件.因此,组长给分了任务,让我们各自去研究不同的图表插件.用了一两天的时间,对java这块的图表插件做了一个简单的研究.java方向的图报表还是有很多很多的,例如,在业界颇具口碑的商业插件--ChartDirector.JavaScript图表 JScharts 等,以及开源插件--JFreeChart(源码免费,文档付费).JasperReports 等. 现状 随着信息化时代的到来,计算机的应用也越来越广

利用php比较精确的统计在线人数的办法

利用php比较精确的统计在线人数的办法,注意这里所说的精确是指个数,如果需要精确在时间上,则需要根据实际情况调整代码中的有效时间.(自己没有写,从别人那拿过来的,先放着然后再研究) <?php//author:www.scutephp.com$filename='online.txt';//数据文件$cookiename='VGOTCN_OnLineCount';//cookie名称$onlinetime=600;//在线有效时间,单位:秒 (即600等于10分钟) $online=file($

一个小栗子聊聊JAVA泛型基础

背景 周五本该是愉快的,可是今天花了一个早上查问题,为什么要花一个早上?我把原因总结为两点: 日志信息严重丢失,茫茫代码毫无头绪. 对泛型的认识不够,导致代码出现了BUG. 第一个原因可以通过以后编码谨慎的打日志来解决,我们今天主要来一起回顾下JAVA泛型基础. 一个小栗子 先看下面一个例子,test1实例化一个List容器的时候没有指定泛型参数,那么我们可以往这个容器里面放入任何类型的对象,这样是不是很爽?但是当我们从容器中取出容器中的对象的时候我们必须小心翼翼,因为容器中的对象具有运行时的类

py爬虫 —— 三个爬虫的小栗子

三个爬虫的小栗子 第一个例子 —— 京东商品的爬取案例 import requests def getHTMLtext(url): try: r = requests.request('get' ,url ) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except: return "出现异常" url = "https://item.jd.com/100005477055.html&

POJ3928 Pingpong(统计比 K 小的个数 + 树状数组)

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2691   Accepted: 996 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To im

ajax跨域请求 小栗子 jsonP

跨域简单理解就是跨服务调用方法 一个常见的ajax模板  前台jsp 后台接受请求 运行结果 结局方法 返回成功 本栗子楼主按视频教程截图........