Listener监听器

1.Listener监听器介绍

  1. Listener监听器是JavaWeb三大组件之一。JavaWeb三大组件分别是:Servlet程序,Listener监听器,Filter过滤器。
  2. Listener是JavaEE的规范,即接口。
  3. 监听器的作用是,监听某种变化(一般就是对象的创建/销毁,属性变化),触发对象方法完成相应的任务。
  4. JavaWeb中的监听器共八个,目前最常用的是ServletContextListener,ServletContextAttributeListener,HttpSessionListener和ServletRequestListener

2.JavaWeb的监听器

2.1ServletContextListener监听器

  1. 作用:监听ServletContext创建或者销毁(当我们web应用启动时,Tomcat就会创建ServletContext对象),即生命周期监听
  2. 应用场景:
    • 加载初始化的配置文件;比如spring的配置文件
    • 任务调度(配合定时器Timer/TimerTask)
  3. 相关方法:
    • void contextInitialized(ServletContextEvent sce):创建ServletContext对象时触发
    • void contextDestroyed(ServletContextEven sce):销毁ServletContext对象时触发

应用实例

  1. 首先创建一个项目,添加web支持,因为listener监听器是Servlet规范,要使用就要引入Servlet.jar包

    day25-Listener监听器

  2. 创建一个普通类,如果该类实现了某个监听接口,那么此类就是一个监听器。该类可以监听的事件由该类实现的监听接口决定:

    package com.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    /**
     * 1.当一个类实现了 ServletContextListener 接口时
     * 2.该类就是一个监听器
     * 3.该类可以监听的事件由该类实现的监听接口决定 ,比如实现ServletContextListener接口,
     * 那么该类就可以监听ServletContext对象的创建和销毁,以此类推
     * 4.下面的MyServletContextListener就是一个监听者
     * 5.当web应用启动时,就会产生ServletContextEvent事件,会调用监听器的对应事件处理方法
     * 如:contextInitialized(),同时会传递 事件对象
     * 6.程序员可以通过 ServletContextEvent 事件对象,来获取需要的信息,然后再进行业务处理
     * 7.Tomcat怎么知道这个监听器存在呢? 因为我们需要在web.xml文件中进行配置,
     * 一旦配置后,tomcat启动后就会反射实例化该监听器,放到容器里面去管理
     */
    public class MyServletContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            ServletContext servletContext = servletContextEvent.getServletContext();
            System.out.println("MyServletContextListener监听到=" +
                    servletContext + "被创建...");
            //如果我们获取到ServletContext对象..可以进行业务处理
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            ServletContext servletContext = servletContextEvent.getServletContext();
            System.out.println("MyServletContextListener监听到=" +
                    servletContext + "被销毁...");
            //比如可以对ServletContext 数据进行处理,或者日志的管理...
            System.out.println("进行处理工作...");
        }
    }
    
  3. 配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <!--配置监听器-->
        <listener>
            <listener-class>com.listener.MyServletContextListener</listener-class>
        </listener>
    </web-app>
    
  4. 配置Tomcat

  5. 点击启动tomcat时,我们可以看到监听器被触发了:

    day25-Listener监听器

  6. 点击停止tomcat时,可以看到监听器再一次被触发:

    day25-Listener监听器

2.2ServletContextAttributeListener监听器

  1. 作用:监听ServletContext属性的变化
  2. 相关方法:
    • void attributeAdded(ServletContextAttributeEvent event):添加属性时调用
    • void attributeReplaced(ServletContextAttributeEvent event):替换属性时调用
    • void attributeRemoved(ServletContextAttributeEvent event):移除属性时调用

应用实例

  1. 创建监听器:MyServletContextAttributeListener
package com.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("MyServletContextAttributeListener 监听到添加属性.." +
                servletContextAttributeEvent.getName() + "=" +
                servletContextAttributeEvent.getValue());
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("MyServletContextAttributeListener 监听到删除属性.." +
                servletContextAttributeEvent.getName() + "=" +
                servletContextAttributeEvent.getValue());
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("MyServletContextAttributeListener 监听到修改属性.." +
                servletContextAttributeEvent.getName() + "=" +
                servletContextAttributeEvent.getValue());
    }
}
  1. 创建servlet:HiServlet
package com.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class HiServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //给ServletContext对象操作属性
        ServletContext servletContext = getServletContext();
        //添加属性
        servletContext.setAttribute("name", "杰克");
        //修改属性
        servletContext.setAttribute("name", "托马斯");
        //删除属性
        servletContext.removeAttribute("name");

        System.out.println("HiServlet 处理完毕...");
    }
}
  1. web.xml:配置监听器和servlet
<!--配置监听器-->
<listener>
    <listener-class>com.listener.MyServletContextAttributeListener</listener-class>
</listener>
<!--配置HiServlet-->
<servlet>
    <servlet-name>HiServlet</servlet-name>
    <servlet-class>com.HiServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HiServlet</servlet-name>
    <url-pattern>/hiServlet</url-pattern>
</servlet-mapping>
  1. 重新发布tomcat,在浏览器中访问servlet,后台输出如下:

    day25-Listener监听器

2.3HttpSessionListener监听器

  1. 作用:监听Session创建或销毁,即生命周期监听
  2. 相关方法:
    • void sessionCreated(HttpSessionEvent se):创建session时调用
    • void sessionDestroyed(HttpSessionEvent se):销毁session时调用
  3. 使用方法和前面一样,可以用于监听用户上线,离线

应用实例

  1. 创建监听器:MyHttpSessionListener
package com.listener;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyHttpSessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        //当session被创建时,设置一个生命周期10s
        session.setMaxInactiveInterval(10);
        System.out.println("MyHttpSessionListener 监听到session创建= " + session.getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("MyHttpSessionListener 监听到session销毁= " + session.getId());
    }
}
  1. 修改HiServlet代码:
package com.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class HiServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session对象
        request.getSession();
        System.out.println("HiServlet 处理完毕...");
    }
}
  1. 配置监听器:
<listener>
    <listener-class>com.listener.MyHttpSessionListener</listener-class>
</listener>
  1. 现在我们重启Tomcat,可以看到还没有访问HiServlet,就已经创建了两个session。这是因为启动Tomcat时,会默认访问项目首页面,tomcat会自动创建两个session,这里忽略即可。

    day25-Listener监听器

  2. 在浏览器访问HiServlet,可以看到后台首先创建了一个session,在设置的生命周期内不访问该session,显示该session被销毁。

    day25-Listener监听器

HttpSessionListener监听器可以用于监听用户上线离线

注意:这里的session不是浏览器一关闭就销毁,session的销毁是服务器端去轮询决定的,因此如果想要用户浏览器一关闭就销毁session,可以通过前端在用户浏览器关闭之前,向服务器发送一个通知,服务器收到通知后销毁该session即可。

2.4HttpSessionAttributeListener监听器

  1. 作用:监听Session属性的变化
  2. 相关方法:
    • void attributeAdded(ServletRequestAttributeEvent event):添加属性时调用
    • void attributeReplaced(ServletRequestAttributeEvent event):替换属性时调用
    • void attributeRemoved(ServletRequestAttributeEvent event):移除属性时调用
  3. 使用少,使用方法和前面一样。

应用实例

  1. 创建监听器:MyHttpSessionAttributeListener
package com.listener;

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

public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {

    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("MyHttpSessionAttributeListener 监听到 session添加属性= "
                + httpSessionBindingEvent.getName() + "=" + httpSessionBindingEvent.getValue());
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("MyHttpSessionAttributeListener 监听到 session删除属性= "
                + httpSessionBindingEvent.getName() + "=" + httpSessionBindingEvent.getValue());
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("MyHttpSessionAttributeListener 监听到 session修改属性= "
                + httpSessionBindingEvent.getName() + "=" + httpSessionBindingEvent.getValue());
    }
}
  1. 修改HiServlet
package com.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class HiServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session对象
        HttpSession session = request.getSession();
        //添加属性
        session.setAttribute("age", 888);
        //修改属性
        session.setAttribute("age", 999);
        //删除属性
        session.removeAttribute("age");
        System.out.println("HiServlet 处理完毕...");
    }
}
  1. 配置监听器
<listener>
    <listener-class>com.listener.MyHttpSessionAttributeListener</listener-class>
</listener>
  1. redeployTomcat,在浏览器访问hiServlet,后台输出如下:

    day25-Listener监听器

2.5ServletRequestListener监听器

  1. 作用:监听Request创建或者销毁,即Request对象的生命周期监听
  2. 相关方法:
    • void requestInitialized(ServletRequestEvent sre):创建request对象时触发
    • void requestDestroyed(ServletRequestEvent sre):销毁request对象时触发
  3. 可以用来监控某个IP访问我们网站的频率,做日志记录,或者访问资源的情况等。

应用实例

  1. 创建监听器:MyServletRequestListener
package com.listener;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;

public class MyServletRequestListener implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("MyServletRequestListener 监听到request对象被创建 ");
        ServletRequest servletRequest = servletRequestEvent.getServletRequest();
        System.out.println("记录访问日志...");
        System.out.println("访问IP= " + servletRequest.getRemoteAddr());
        System.out.println("访问的资源= " + ((HttpServletRequest) servletRequest).getRequestURL());

    }

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("MyServletRequestListener 监听到request对象被销毁...");
    }
}
  1. hiServlet不做修改

  2. 配置监听器:

<listener>
    <listener-class>com.listener.MyServletRequestListener</listener-class>
</listener>
  1. redeployTomcat,在浏览器访问hiServlet,后台输出如下:

    (中间的session监听可忽略)

    day25-Listener监听器

  2. 访问项目首页面,后台输出如下:

    day25-Listener监听器

2.6ServletRequestAttributeListener监听器

  1. 作用:监听Request属性变化
  2. 相关方法
    • void attributeAdded(ServletRequestAttributeEvent srae):添加属性时调用
    • void attributeReplaced(ServletRequestAttributeEvent srae):替换属性时调用
    • void attributeRemoved(ServletRequestAttributeEvent srae):移除属性时调用
  3. 使用方法和前面类似

2.7HttpSessionBindingListener感知监听器

该监听器是用来绑定数据的。如果一个对象实现了HttpSessionBindingListener接口,当这个对象被绑定到Session中或者从session中被删除时,Servlet容器会通知这个对象,而这个对象在接收到通知后,可以做一些初始化或清除状态的操作。

2.8HttpSessionActivationListener感知监听器

HttpSessionActivationListener用于监控实现类本身,当实现类对象被添加到session属性中后,session对象序列化(钝化)前和反序列化(活化)后都会被执行

相应的方法:

  • sessionWillPassivate(HttpSessionEvent se): session钝化前执行(session从内存到硬盘)
  • sessionDidActivate(HttpSessionEvent se):session活化后执行(session从硬盘到内存)