Web Listener --- 精确地监控在线用户的状态

使用Web Listener 需要两个步骤;

1.定义Listener 实现类
2.通过注解或 在web.xml文件配置



一  采用的web事件监听器接口有如下:

1.ServletContextListener :用于web应用的启动与关闭 

方法:
--public void contextInitialized(ServletContextEvent sce)  启动web时调用

--public void contextDestroyed(ServletContextEvent sce)


2.ServletContextAttributeListener : 用于监听ServletContext(application)范围内属性的变化

--public void attributeAdded(ServletContextAttributeEvent scae)
--public void attributeRemoved(ServletContextAttributeEvent scae)

--public void attributeReplaced(ServletContextAttributeEvent scae)


3.ServletRequestListener :用于用户请求

--public void contextInitialized(ServletRequestEvent sce)  

--public void contextDestroyed(ServletRequestEvent sresce)


4.ServletRequestAttributeListener

--public void attributeRmoved(ServletRequestAttributeEvent srae)
--public void attributeRemoved(ServletRequestAttributeEvent srae)

--public void attributeReplaced(ServletRequestAttributeEvent srae)


5.HttpSessionListener 

--public void sessionCreate(HttpsessionEvent hse)
--public void sessionDestroyed(HttpsessionEvent hse)



6.HttpSessionAttributeListener 

--public void attributeRmoved(ServletSessionAttributeEvent ssae)
--public void attributeRemoved(ServletSessionAttributeEvent ssae)

--public void attributeReplaced(ServletSessionAttributeEvent ssae)


二 应用--- 更精确地监听在线用户的状态

思路:

1.定义ServletRequestListener,负责监听每个用户请求,当用户的请求到达时,如果是新的会话,将记录(sessionId、用户名、用户IP、正在访问的资源、访问时间)保存下来(插入数据库);如果是老的用户会话则更新记录;

2.启动后台线程,每隔一段时间检查上面的记录,设定离线时间,如果是离线则删除。线程使用ServletContextListener ;

RequestListener.java  代码

@WebListener
public class RequestListener implements ServletRequestListener {
// 当用户请求到达、被初始化时触发该方法
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest) sre
.getServletRequest();
HttpSession session = request.getSession();
// 获取session ID
String sessionId = session.getId();
// 获取访问的IP和正在访问的页面
String ip = request.getRemoteAddr();
String page = request.getRequestURI();
String user = (String) session.getAttribute("user");
// 未登录用户当游客处理
user = (user == null) ? "游客" : user;
try {
DbDao dd = new DbDao("com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/online_inf", "root", "123456");
ResultSet rs = dd.query(
"select * from online_inf where session_id=?", true,
sessionId);
// 如果该用户对应的session ID存在,表明是旧的会话
if (rs.next()) {
// 更新记录
rs.updateString(4, page);
rs.updateLong(5, System.currentTimeMillis());
rs.updateRow();
rs.close();
} else {
// 插入该用户的在线信息
dd.insert("insert into online_inf values(? , ? , ? , ? , ?)",
sessionId, user, ip, page, System.currentTimeMillis());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}


// 当用户请求结束、被销毁时触发该方法
public void requestDestroyed(ServletRequestEvent sre) {
}
}


OnlineListener.java 代码:

@WebListener
public class OnlineListener implements ServletContextListener {
// 超过该时间(10分钟)没有访问本站即认为用户已经离线
public final int MAX_MILLIS = 5 * 60 * 1000;


// 应用启动时触发该方法
public void contextInitialized(ServletContextEvent sce) {
// 每10秒检查一次
new javax.swing.Timer(1000 * 10, new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
DbDao dd = new DbDao("com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/online_inf", "root",
"123456");
ResultSet rs = dd.query("select * from online_inf", false);
StringBuffer beRemove = new StringBuffer("(");
while (rs.next()) {
// 如果距离上次访问时间超过了指定时间
if ((System.currentTimeMillis() - rs.getLong(5)) > MAX_MILLIS) {
// 将需要被删除的session ID添加进来
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_inf where session_id in "
+ beRemove.toString());
}
dd.closeConn();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}


public void contextDestroyed(ServletContextEvent sce) {
}
}

在线监听用户的状态 online.jsp

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="java.sql.*,com.yd.dao.DbDao" %>
<!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>
<title> 用户在线信息 </title>
</head>
<body>
在线用户:
<table width="640" border="1">
<%
DbDao dd = new DbDao("com.mysql.jdbc.Driver"
, "jdbc:mysql://localhost:3306/online_inf"
, "root"
, "123456");
// 查询online_inf表(在线用户表)的全部记录
ResultSet rs = dd.query("select * from online_inf" , false);
while (rs.next())
{%>
<tr>
<td><%=rs.getString(1)%>
<td><%=rs.getString(2)%>
<td><%=rs.getString(3)%>
<td><%=rs.getString(4)%>
</tr>
<%}%>
</body>
</html>

注:本人不喜欢直接在jsp页面查询数据库,因临时所写

online_inf.sql  语句:

drop database online_inf;

create database online_inf;

use online_inf;

create table online_inf
(
 session_id varchar(255) primary key,
 username varchar(255),
 user_ip varchar(255),
 access_res varchar(255),
 last_access bigint
);

最后感叹下,打字的速度需要练练.....

你可能感兴趣的:(Web,listener,listener)