Listener是Servlet的监听器,可以监听客户端的请求和服务器的操作,并自动激发一些操作,比如监听在线用户数量。常用接口如下
- ServletContextListener 监听ServletContext的创建与销毁
当创建时激发contextInitialized(ServletContextEvent sce)
销毁时激发contextDestroyed(ServletContextEvent sce)
- ServletContextAttributeListener 监听ServletContext(application)范围内属性的变化
添加属性时激发attributeAdded(ServletContextAttributeEvent event)
删除属性时激发attributeRemoved(ServletContextAttributeEvent event)
替换属性时激发attributeReplaced(ServletContextAttributeEvent event)
- ServletRequestListener 监听用户request的创建与销毁
创建时激发requestInitialized(ServletRequestEvent event)
销毁时激发requestDestroyed(ServletRequestEvent event)
- ServletRequestAttributeListener 与ServletContextAttributeListener类似,只是监视的是request范围内的属性变化
attributeAdded(ServletRequestAttributeEvent event)
attributeRemoved(ServletRequestAttributeEvent event)
attributeReplaced(ServletRequestAttributeEvent event)
- HttpSessionListener 监听用户session的创建与销毁
创建时激发sessionCreated(HttpSessionEvent se)
销毁时激发sessionDestroyed (HttpSessionEvent se)
- HttpSessionAttributeListener 与ServletContextAttributeListener类似,只是监视的是session范围内的属性变化
attributeAdded(HttpSessionBindingEvent se)
attributeRemoved(HttpSessionBindingEvent se)
attributeReplaced(HttpSessionBindingEvent se)
例1,统计在线人数,并在ServletContext创建、销毁、修改属性时在控制台打印
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class OnlineUserLitener implements HttpSessionListener,ServletContextListener,ServletContextAttributeListener {
private long onlineUserCount = 0;
public long getOnlineUserCount(){
return onlineUserCount;
}
private void toUpdateCount(HttpSessionEvent event){
event.getSession().setAttribute("onlineUserCount", onlineUserCount);
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
onlineUserCount++;
toUpdateCount(httpSessionEvent);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
onlineUserCount--;
toUpdateCount(httpSessionEvent);
}
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("Servlet context's " + servletContextAttributeEvent.getName().toString() + "added as " + servletContextAttributeEvent.getValue().toString());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("Servlet context's " + servletContextAttributeEvent.getName().toString() + "removed.");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("Servlet context's " + servletContextAttributeEvent.getName().toString() + "changed to." + servletContextAttributeEvent.getValue().toString());
}
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println(servletContextEvent.getServletContext().toString() + "is created");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println(servletContextEvent.getServletContext().toString() + "is destroyed");
}
}
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
主页
在线人数:<%=request.getSession().getAttribute("onlineUserCount") %>
例2,定义一个ServletRequestListener监听所有用户请求,每当请求达到时,将seesion ID、用户名、用户ip、正在访问的页面、访问时间记录到数据库。启动一条线程,每个一段时间检查一遍,如果某条访问记录的时间与当前时间相差过久,就删掉这条记录(这条线程随应用启动而创建,可以考虑有ServletContextListener实现)
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.sql.ResultSet;
import java.sql.SQLException;
@WebListener
public class RequestListener implements ServletRequestListener{
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.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 resultSet = dd.query("select * from omline_inf where session_id = ?",true, sessionId);
if (resultSet.next()){
//更新数据库记录
resultSet.updateString(4, page);
resultSet.updateLong(5,System.currentTimeMillis());
resultSet.updateRow();
resultSet.close();
}
else{
//这是新用户,将访问信息插入数据库
dd.insert("insert into online_inf values(?,?,?,?,?)", sessionId, user, ip, page, System.currentTimeMillis());
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
@WebListener
public class OnlineListener implements ServletContextListener{
//超过该时间后未再次访问,即认为用户离线
public final int MAX_MILLIS = 10 * 60 * 1000; //10分钟
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//每5秒检查一次
new javax.swing.Timer(1000 * 5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try{
DbDao dd = new DbDao("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/online_inf", "root", "123456");
ResultSet resultSet = dd.query("select * from online_inf", false);
StringBuffer toBeRemoved = new StringBuffer("{");//存放需要被删除的session ID
//找出需要被删除的session ID
while (resultSet.next()){
if ((System.currentTimeMillis() - resultSet.getLong(5)) > MAX_MILLIS){
toBeRemoved.append("'");
toBeRemoved.append(resultSet.getString(1));
toBeRemoved.append("',");
}
}
//将这些session ID从数据库中删除
if (toBeRemoved.length() > 3){
toBeRemoved.setLength(toBeRemoved.length() - 3);
toBeRemoved.append("}");
dd.modify("delete from online_inf where session_id in " + toBeRemoved.toString());
}
dd.closeConn();
}
catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
<%@ page language="java" contentType="text/html; charset=GBK", pageEncoding="GBK"%>
<%@ page import="java.sql.*,lee.*" %>
在线用户
在线用户:
<%
DbDao dd = new DbDao("com.sql.jdbc.Driver", "jdbc:mysql://localhost:3306/online_inf", "root", "123456");
ResultSet rs = dd.query("select * from online_inf", false);
while(rs.next()){
%>
<%=rs.getString(1)%>
<%=rs.getString(2)%>
<%=rs.getString(3)%>
<%=rs.getString(4)%>
<%=rs.getString(5)%>
<%}%>