监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

分类:

按监听的对象划分,可以分为

ServletContext对象监听器
HttpSession对象监听器
ServletRequest对象监听器

按监听的事件划分

对象自身的创建和销毁的监听器
对象中属性的创建和消除的监听器
session中的某个对象的状态变化的监听器

示例:用监听器统计网站在线人数

原理:每当有一个访问连接到服务器时,服务器就会创建一个session来管理会话。那么我们就可以通过统计session的数量来获得当前在线人数。

监听器应用一般统计在线人数,闲着没事,写个笔记,我们项目中是这样做的

首先定义一个servlet 这个servelt 在服务器启动时,就会调用,初始化:

实现累计访问量的一个方法

1.web.xml的配置

1
2
3
4
5
6
7
8
<!-- added by li'n for 登陆页面自动读取访问数  on 2013-04-15  the beginning -->
<servlet>
<servlet-name>VisitCounts</servlet-name>
<servlet-class>com.sysware.framework.login.VisitCounts</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<!-- added by li'n for 登陆页面自动读取访问数 on 2013-04-15 the end -->

2.项目登录页面可以获取访问本项目的总人数(init方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.sysware.framework.login;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import javax.servlet.http.HttpServlet;

/**
* @version 1.0
* @author li'n on 系统工程部
* @since 2013-04-15 17:00
*
*/
public class VisitCounts extends HttpServlet{

/**
*
*/
private static final long serialVersionUID = -6737156348721467846L;
//累计访问量
public static int counts = 0;

public static void setCounts(int counts) {
VisitCounts.counts = counts;
}

/**
*
* @return 历史访问量
*/
public int getCounts() {
return counts;
}

/**
* 服务器启动时读取文件中的历史访问量
*/
public void init()
{
//获取visitCount.txt的文件路径
String p = this.getClass().getClassLoader().getResource("").getPath();
File file = new File(p+File.separator +"visitCount.txt");

//读取文件中的数字,即系统的历史访问量
if (file.exists()) {
readFile(file);
} else {
try {
file.createNewFile();
readFile(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 读取文件file中的访问量数据
*/
@SuppressWarnings("static-access")
public void readFile(File file){
BufferedReader reader = null;
String tempString = null;
try {
reader = new BufferedReader(new FileReader(file));
while((tempString = reader.readLine()) != null)
{
VisitCounts.counts = Integer.parseInt(tempString);
System.out.println();
this.setCounts(counts);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}



}

3.在用户登录时,数量加1并用流写到文件里面(doLogin方法里面处理)

1
2
3
4
5
6
7
8
9
10
if(loginInfo.isSuccess())
{
//added by li'n for 访问量统计 on 2013-04-19 the beginning
//登录成功,访问量加1
VisitCounts.setCounts(VisitCounts.counts + 1);
//将访问量更新到文件visitCount.txt
writeFile();
//added by li'n for 访问量统计 on 2013-04-19 the end
}<br>/**<br> * 将访问量更新到文件visitCount.txt<br> * @return 历史访问量<br> * @author li'n on 系统工程部<br> * @since 2013-04-19 <br> */<br> public void writeFile(){<br> <br> FileWriter filewrite = null;<br> try {<br> <br> //获得文件路径<br> filewrite = new FileWriter(this.getClass().getClassLoader().getResource("").getPath()+File.separator +"visitCount.txt");<br> <br> //将访问量写入文件<br> int o = VisitCounts.counts;<br> filewrite.write(o + "\r\n");<br> filewrite.flush();<br> filewrite.close();<br> } catch (Exception e) {<br> e.printStackTrace();<br> }<br><br> }

以上,是实现累计访问量的一个方法;

下面说说实现在线人数,这个就要用到监听器的方式

实现在线人数

首先还是在 web.xml中配置你所写的监听器

1
2
3
4
<!-- 在线用户session监听器 -->
<listener>
<listener-class>com.sysware.framework.login.OnlineSessionListener</listener-class>
</listener>

2.监听器类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.sysware.framework.login;

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

import com.sysware.framework.commons.SystemConstants;

/**
*
*
* 在线session监听器
*
* @version : 1.0
* @since : 2012-5-21下午08:46:02
* @team : 系统管理
* @author : liuxj
*/
public class OnlineSessionListener implements HttpSessionAttributeListener {


@Override
public void attributeAdded(HttpSessionBindingEvent event) {
if (SystemConstants.SESSION_KEY.equals(event.getName())) {
OnlineUserContext.getInstance().addSession(event.getSession());
}
}

@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if (SystemConstants.SESSION_KEY.equals(event.getName())) {
OnlineUserContext.getInstance().removeSession(event.getSession());
}
}

@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if (SystemConstants.SESSION_KEY.equals(event.getName())) {
OnlineUserContext.getInstance().replaceSession(event.getSession());
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
package com.sysware.framework.login;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpSession;

import com.sysware.framework.commons.SystemConstants;
import com.sysware.framework.eobs.commons.ObjectCloneUtils;
import com.sysware.utils.SyswareUtil;

/**
* copyright : Sysware Technology Co., Ltd
*
* 在线用户信息上下文
*
* @version : 1.0
* @since : 2012-5-21下午08:31:07
* @team : 系统管理
* @author : liuxj
*/
public class OnlineUserContext {
private static OnlineUserContext onlineUserContext;

// 用户在线信息
private Map<String, HttpSession> onlineUserMap;

private OnlineUserContext() {
onlineUserMap = new HashMap<String, HttpSession>();
}

/**
* 获取在线用户上下文实例
*
* @since : 2012-5-23:下午05:47:55
* @return 在线用户上下文实例
*/
public static OnlineUserContext getInstance() {
return onlineUserContext == null ? onlineUserContext = new OnlineUserContext()
: onlineUserContext;
}

/**
* 加入session触发
*
* @since : 2012-5-21:下午09:02:26
* @param session
* session对象
*/
synchronized void addSession(HttpSession session) {

onlineUserMap.put(session.getId(), session);
}

/**
* 移除Session
*
* @since : 2012-5-21:下午09:02:56
* @param session
* session对象
*/
synchronized void removeSession(HttpSession session) {
if (onlineUserMap.containsKey(session.getId())) {
onlineUserMap.remove(session.getId());
}
}

/**
* 替换Session
*
* @since : 2012-5-21:下午09:03:18
* @param session
* session对象
*/
synchronized void replaceSession(HttpSession session) {
addSession(session);
}
/**
* 根据用户ID判断是否登录
*
* @since : 2013-1-28:下午02:01:31
* @param userId
* 用户ID
* @return true已经登录|false未登录
*/
public boolean isLogged(String userId) {
List<OnlineUserInfo> list = getOnlineUserInfoList();
for (OnlineUserInfo info : list) {
if (info.isLogged() && info.getUserId().equals(userId)) {
return true;
}
}
return false;
}
/**
* 根据sessionId获取session
* @since : 2012-12-17:下午01:06:11
* @param sessionId sessionId
* @return session
*/
public HttpSession getSession(String sessionId) {
return onlineUserMap.containsKey(sessionId) ? onlineUserMap.get(sessionId) : null;
}

/**
* 根据sessionId移除session
* @since : 2012-12-17:下午01:05:39
* @param sessionId sessionId
*/
public void removeSession(String sessionId) {
HttpSession session = getSession(sessionId);
if(!SyswareUtil.isEmpty(session)) {
session.invalidate();
session = null;
}
}

/**
* 获取当前登录操作用户数量
*
* @since : 2012-5-21:下午09:20:54
* @return 登录操作用户数量
*/
public int getLoginUserCount() {
int num = 0;
List<OnlineUserInfo> list = getOnlineUserInfoList();
for(OnlineUserInfo info : list) {
if(info.isLogged()) {
num ++;
}
}
return num;
}

/**
* 获取当前未登录的操作用户数量
*
* @since : 2012-5-21:下午09:21:14
* @return 未登录的操作用户数量
*/
public int getNoLoginUserCount() {
int num = 0;
List<OnlineUserInfo> list = getOnlineUserInfoList();
for(OnlineUserInfo info : list) {
if(!info.isLogged()) {
num ++;
}
}
return num;
}

/**
* 获取当前操作用户总数
*
* @since : 2012-5-21:下午09:22:16
* @return 操作用户总数
*/
public int getOperatorCount() {
return getOnlineUserInfoList().size();
}

/**
* 获取当前操作用户列表
*
* @since : 2012-5-22:上午10:11:39
* @return 操作用户列表
*/
public synchronized List<OnlineUserInfo> getOnlineUserInfoList() {
List<OnlineUserInfo> list = new ArrayList<OnlineUserInfo>();
Iterator<Entry<String, HttpSession>> iterator = onlineUserMap
.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, HttpSession> entry = iterator.next();
OnlineUserInfo info = ObjectCloneUtils.clone(getOnlineUserInfo(entry.getKey()));
info.setSessionId(entry.getKey());
list.add(info);
}
return list;
}

/**
* 获取在线用户信息
*
* @since : 2012-5-21:下午09:14:01
* @param sessionId
* session的ID
* @return 在线用户信息
*/
private OnlineUserInfo getOnlineUserInfo(String sessionId) {
HttpSession session = getSession(sessionId);
return SyswareUtil.isEmpty(session) ? null : (Operator) session.getAttribute(SystemConstants.SESSION_KEY);
}
}

上面的方法,一个是在线统计人数,一个是实现总访问量,自己项目中运用的,做个笔记。

页面

1
2
3
<div class="visit">当前访问数:<span id="nowVisitCount" style="color:#5374B1;"><%=OnlineUserContext.getInstance().getLoginUserCount()  %></span></div>
<div class="count">累计访问数:<span id="historyVisitCount" style="color:#5374B1;"><%=new LoginServiceImpl().getCounts()%></span></div>