监听器

Servlet 监听器用于监听Java Web应用中某些对象信息的创建、销毁、增加、修改、删除等动作的发生,然后作出相应的响应处理。常用于统计在线人数和在线用户、系统加载时信息初始化、统计网站的访问量等等。

创建不同功能的监听器类,需要实现不同的监听接口。一个监听器类可以实现多个接口,即可以使多种功能的监听器一起工作。根据监听的对象可将监听器划分为:ServletContext 对象监听器HttpSession对象监听器以及ServletRequest 对象监听器。根据监听的事件可将监听器划分为:对象自身的创建和销毁的监听器对象中属性的创建、修改和消除的监听器以及session中某个对象状态变化的监听器。1监听对象自身创建和销毁的监听器

HttpSessionListener、ServletContextListener 和 ServletRequestListener 监听接口分别监听 session、context 和 request 对象的创建与销毁。

·HttpSessionListener:监听session的创建与销毁.创建 session时执行 sessionCreated-(HttpSessionEvent se)方法.超时或执行 session.invalidate()时执行 sessionDestroyed-(HttpSessionEvent se)方法。该监听器可用于统计在线人数、记录访问日志等

ServletContextListener:监听 context的创建与销毁。context代表当前 Web 应用程序。服务器启动时执行 contextInitialized(ServletContextEvent sce)方法。服务器关闭时执行 contextDestroyed(ServletContextEvent sce)方法。该监听器可用于启动时获取web.xml中配置的初始化参数,可作为定时器、加载全局属性对象、创建全局数据库连接、加载缓存信息等

ServletRequestListener:监听 request的创建与销毁。用户每次请求 request都将执行requestInitialized(ServletRequestEvent sre)方法。request处理完毕自动销毁前执行 requestDestroyed(ServletRequestEvent sre)方法。该监听器可用于读取request 参数,记录访问历史。

创建一个名为 listener的包,并在包中创建一个名为MyObjectListener 的监听器类,该监听器类实现 HttpSessionListener,ServletContextListener 和

ServletRequestListener 监听接口。

package listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
//监听类
public class MyObjectListener implements HttpSessionListener,ServletContextListener,ServletRequestListener{
  @Override
  public void sessionCreated(HttpSessionEvent se) {
     HttpSession session = se.getSession();  
       System.out.println("新创建一个session, ID为: " + session.getId());  
  }
  @Override
  public void sessionDestroyed(HttpSessionEvent se) {
     HttpSession session = se.getSession();  
     System.out.println("销毁一个session, ID为: " + session.getId());
  }
  @Override
  public void contextInitialized(ServletContextEvent sce) {
     ServletContext servletContext = sce.getServletContext();  
     System.out.println("即将启动" + servletContext.getContextPath());  
  }
  @Override
  public void contextDestroyed(ServletContextEvent sce) {
    ServletContext servletContext = sce.getServletContext();  
    System.out.println("即将关闭" + servletContext.getContextPath());
  }
  @Override
  public void requestInitialized(ServletRequestEvent sre) {
    HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();    
        String uri = request.getRequestURI();  
        uri = request.getQueryString() == null ? uri : (uri + "?" + request.getQueryString());  
        request.setAttribute("dateCreated", System.currentTimeMillis());  
        System.out.println("IP " + request.getRemoteAddr() + " 请求 " + uri); 
  }
  @Override
  public void requestDestroyed(ServletRequestEvent sre) {
     HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();  
       long time = System.currentTimeMillis() - (Long) request.getAttribute("dateCreated");  
       System.out.println(request.getRemoteAddr() + "请求处理结束, 用时" + time + "毫秒。");  
  }
}

在控制台页面可以看到如下图片

监听器

2监听对象属性变化的监听器

监听对象属性变化的监听器分别为 HttpSessionAttributeListener,ServletContextAttributeListener,ServletRequestAttributeListener.这3个监听接口分别用于监听session,context 和 request的属性变化.当向被监听对象中添加,更新,移除属性时,将分别执行 attributeAdded,attributeReplaced. attributeRemoved 方法

在listener包中创建一个名为MyAttributeListener的监听器类,该监听器类实现HttpSessionAttributeListener监听接口

MyAttributeListener.java

package listener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
//监听对象的属性
public class MyAttributeListener implements HttpSessionAttributeListener{
  @Override
  public void attributeAdded(HttpSessionBindingEvent se) {
       String name = se.getName();  
       System.out.println("新建session属性:" + name + ", 值为:" + se.getValue());
  }
  @Override
  public void attributeReplaced(HttpSessionBindingEvent se) {
    HttpSession session = se.getSession();  
        String name = se.getName();  
        Object oldValue = se.getValue();  
        System.out.println("修改session属性:" + name + ", 原值:" + oldValue + ", 新值:" + session.getAttribute(name));  
  }
  @Override
  public void attributeRemoved(HttpSessionBindingEvent se) { 
       String name = se.getName();  
       System.out.println("删除session属性:" + name + ", 值为:" + se.getValue()); 
  }
}

部署监听器

<listener>
    <listener-class>listener.MyAttributeListener</listener-class>
</listener>

在test.jsp中添加

//验证是否有效
  session.setAttribute("user", "xd");
  session.setAttribute("user", "xdd");
  session.invalidate();
监听器

3监听session某个对象状态变化的监听器

监听绑定到 HttpSeesion域中某个对象状态的事件监听器有 HttpSessionBindingListener,HttpSessionActivationListener.HttpSession中对象的状态有:绑定→解除绑定,钝化→活化。

绑定,通过setAttribute 保存到session对象当中.解除绑定,通过 removeAttribue去除绑定.钝化,将session对象持久化到存储设备上.活化.将session 对象从存储设备上进行恢复.

被实现钝化和活化的监听器对象必须实现Serializable接口,不需要在web.xml中部署

HttpSessionBindingListener:当对象被放到session 中时,执行 valueBound-(HttpSessionBindingEvent event)方法。当对象被从 session 中移除时,执行valueUnbound(HttpSessionBindingEvent event)方法.对象必须实现该监听接口。

HttpSessionActivationListener:当session中的对象被钝化时,执行 sessionWillPassivate(HttpSessionEvent se)方法.当对象被重新加载(活化)时,执行 sessionDidActivate-(HttpSessionEvent se)方法。对象必须实现该监听接口。

listener包中创建一个名为MySeesionListener的监听器类,该监听器类实现 HttpSessionBindingListener,HttpSessionActivationListener,Serializable 接口.

MySessionListener.java

package listener;
import java.io.Serializable;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
public class MySeesionListener implements HttpSessionBindingListener,HttpSessionActivationListener,Serializable {  
    private static final long serialVersionUID = -4780592776386225973L;  
    private String name;  
    /**
     * 活化
     */
    public void sessionDidActivate(HttpSessionEvent se) {  
        HttpSession session = se.getSession();  
        System.out.println(this + "已经成功从硬盘中加载。sessionId: " + session.getId());  
    }  
    /**
     * 即将被钝化到硬盘时  
     */
    public void sessionWillPassivate(HttpSessionEvent se) {  
        HttpSession session = se.getSession();  
        System.out.println(this + "即将保存到硬盘。sessionId: " + session.getId());  
    }  
 
    /**
     * 绑定到session  
     */
    public void valueBound(HttpSessionBindingEvent event) {  
        HttpSession session = event.getSession();  
        String name = event.getName();  
        System.out.println(this + "被绑定到session \"" + session.getId() + "\"的" + name + "属性上");  
    }  
 
    /**
     * 从session中移除后  
     */
    public void valueUnbound(HttpSessionBindingEvent event) {  
        HttpSession session = event.getSession();  
        String name = event.getName();  
        System.out.println(this + "被从session \"" + session.getId() + "\"的" + name + "属性上移除");  
    }  
    @Override  
    public String toString() {  
        return "MySeesionListener(" + name + ")";  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}

test.jsp中添加

  MySeesionListener msl=new MySeesionListener();
  msl.setName("测试session内监听器");
  //绑定到session
  session.setAttribute("msl", msl);
  //从session移除
  session.removeAttribute("msl");
监听器

4监听器的实际应用-统计在线人数

做一个网站,实现在线人数统计。可以通过 ServletContextListener 监听,当

Web应用上下文启动时,在ServletContext 中添加一个List用来准备存放在线的用户名。然后通过 HttpSessionAttributeListener监听,当用户登录成功,把用户名设置到Session中,同时将用户名放到 ServletContext的List中。最后通过 HttpSessionListener监听,当用户注销会话时,将用户名从应用上下文范围中的List列表中删除。

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  <form action="loginServlet" method="post">
    用户名:<input type="text" name="username"> 
    <input type="submit"value="登录">
  </form>
</body>
</html>

login.jsp

package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doPost(request, response);
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8"); // 设置响应内容类型
    String username = request.getParameter("username"); // 获取请求参数中的用户名
    // 往session中添加属性,会触发HttpSessionAttributeListener中的attributeAdded方法
    if (username != null && !username.equals("")) {
      request.getSession().setAttribute("username", username);
    }
    // 从应用上下文中获取在线用户名列表
    List<String> online = (List<String>) getServletContext().getAttribute("online");
    System.out.println("LoginServlet" + online);
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    out.println("");
    out.println("  <title>用户列表</title>");
    out.println("  ");
    out.println("当前用户是:" + username);
    out.print("    <hr><h3>在线用户列表</h3>");
    int size = online == null ? 0 : online.size();
    for (int i = 0; i < size; i++) {
      if (i > 0) {
        out.println("<br>");
      }
      out.println(i + 1 + "." + online.get(i));
    }
    // 注意: 要对链接URL进行自动重写处理
    out.println("<hr/><a href=\"" + response.encodeURL("logoutServlet") + "\">注销</a>");
    out.println("  ");
    out.println("");
    out.flush();
    out.close();
  }
}

logout.jsp

package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/logoutServlet")
public class LogoutServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  public void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        this.doPost(request, response);  
    }  
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        request.setCharacterEncoding("utf-8");    //设置响应内容类型      
        //销毁会话,会触发SessionLinstener中的sessionDestroyed方法  
        request.getSession().invalidate();    
        //从应用上下文中获取在线用户名列表  
        List<String> online = (List<String>)getServletContext().getAttribute("online");      
        response.setContentType("text/html;charset=utf-8");  
        PrintWriter out = response.getWriter();  
        out.println("");  
        out.println("  <title>用户列表</title>");  
        out.println("  ");  
        out.print("    <h3>在线用户列表</h3>");  
        int size = online == null ? 0 : online.size();  
        for (int i = 0; i < size; i++) {  
            if(i > 0){  
                out.println("<br>");  
            }  
            out.println(i + 1 + "." + online.get(i));  
        }    
        out.println("<hr><a href=\"index.jsp\"'>主页</a>");  
        out.println("  ");  
        out.println("");  
        out.flush();  
        out.close();  
    }  
}

OnlineListener.java

package listener;
import java.util.ArrayList;  
import java.util.List;  
import javax.servlet.ServletContext;  
import javax.servlet.ServletContextEvent;  
import javax.servlet.ServletContextListener;  
import javax.servlet.http.HttpSessionAttributeListener;  
import javax.servlet.http.HttpSessionBindingEvent;  
import javax.servlet.http.HttpSessionEvent;  
import javax.servlet.http.HttpSessionListener;  
public class OnlineListener implements ServletContextListener, HttpSessionAttributeListener, HttpSessionListener {      
    private ServletContext application = null;  
    /**
     * 应用上下文初始时会回调的方法  
     */
    @Override  
    public void contextInitialized(ServletContextEvent e) {  
        //初始化一个application对象  
        application = e.getServletContext();  
        //设置一个列表属性,用于保存在线用户名  
        this.application.setAttribute("online", new ArrayList<String>());  
    }  
    /**
     * 往会话中添加属性时的回调方法  
     */
    @Override  
    public void attributeAdded(HttpSessionBindingEvent e) {  
        //取得用户名列表  
        List<String> onlines = (List<String>) this.application.getAttribute("online");  
        if("username".equals(e.getName())){  
            onlines.add((String) e.getValue());  
        }  
        //将添加后的列表重新设置列application属性中.  
        this.application.setAttribute("online", onlines);  
    }  
    /**
     * 会话销毁时会回调的方法  
     */
    @Override  
    public void sessionDestroyed(HttpSessionEvent e) {  
        //取得用户名列表  
        List<String> onlines = (List<String>) this.application.getAttribute("online");  
        //取得当前用户名  
        String username = (String) e.getSession().getAttribute("username");  
        //将此用户从列表中删除  
        onlines.remove(username);  
        //讲删除后的列表重新设置到application属性中.  
        this.application.setAttribute("online", onlines);  
    }  
}

发表评论

登录后才能评论
联系客服
联系客服
分享本页
返回顶部