监听器

作者: 码而优则仕 | 来源:发表于2020-08-26 08:43 被阅读0次

    监听器

    为了能够在 Servlet 应用程序中进行事件驱动编程,Servlet API 提供了一整套事件类和监听器接口。所有事件类均源自java.util.Event,并且监听器在以下三个不同级别中均可用:ServletContextHttpSession,ServletRequest.

    监听器接口和注册

    ServletContextListener

    ServletContextAttributeListener

    HttpSessionListener

    HttpSessionActivationListener

    HttpSessionAttributeListener

    HttpSessionBindingListener

    ServletRequestListener

    ServletRequestAttributeListener

    AsyncListener。

    注册监听器有两种方式:注解(@WebListener)/在部署描述符(web.xml)中配置

    <listener>
      <listener-class>
      </listener-class>
    </listener>
    

    ServletContext 监听器

    在ServletContext 级别上有两个监听器接口:ServletContextListener,ServletContextAttributeListener

    ServletContextListener:

    ServletContextListener会对 ServletContext 的初始化和解构做出响应。ServletContext被初始化的时候,Servlet容器会在所有已注册的ServletContextListener中调用 contextInitialized 方法,方法签名如下:

    • void contextInitialized(ServletContextEvent event)

      当ServletContext要被解构和销毁时,Servlet容器会在所有已注册的ServletContextListener中调用 contextDestroyed 方法,方法签名如下:

    • void contextDestroyed(ServletContextEvent event)

      ServletContextEvent是 java.util.EventObject 类的派生类。其中定义了方法:

      ServletContext getServletContext()

    实例如下:

    JSTL 依赖引入:

    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    
    package cn.com.yuns.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 以注解的方式申明监听器
     *
     * @author wsq
     * @version AppListener.java  2020/7/30  上午8:32 上午
     */
    @WebListener
    public class AppListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            ServletContext servletContext = sce.getServletContext();
            Map<String, String> countries = new HashMap<>();
            countries.put("ca", "China");
            countries.put("jp", "Japan");
            countries.put("am", "American");
            servletContext.setAttribute("countries", countries);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
    
        }
    
    }
    
    <%--
      Created by IntelliJ IDEA.
      User: wsq
      Date: 2020/7/30
      Time: 8:36 上午
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>Country List</title>
    </head>
    <body>
    we operate in these countries:
    <ul>
        <c:forEach items="${countries}" var="country">
            <li>
                    ${country.value}
            </li>
        </c:forEach>
    </ul>
    </body>
    
    </html>
    

    ServletContextAttributeListener:

    每当ServletContext 中添加,删除或替换了某个属性时,所有注册的实现了ServletContextAttributeListener的监听器都会收到通知:

    下面是这个监听器接口定义的三个方法:
    • void attributeAdded(ServletContextAttributeEvent event);

    • void attributeRemoved(ServletContextAttributeEvent event);

    • void attributeReplaced(ServletContextAttributeEvent event);

      在ServletContext 中,添加,删除,替换某个属性时,上上面的三个方法就会被分别调用。ServletContextAttributeEvent派生自 ServletContextAttribute

    Session监听器

    与HttpSession 有关的监听器接口有四个:HttpSessionListener,HttpSessionActivationListener,HttpSessionAttributeListener,HttpSessionBindingListener。

    HttpSessionListener:

    当有HttpSession 被创建或者销毁的时候,Servlet 容器就会调用所有已经注册的HttpSessionListener。

    HttpSessionListener:定义了两个方法:

    • void sessionCteated(HttpSessionEvent event)

    • void sessionDestroyed(HttpSessionEvent event)

      方法参数 HttpSessionEvent 定义了一个方法:

      HttpSession getSession();

    实例如下:

    package cn.com.yuns.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author wsq
     * @version SessionListener.java  2020/7/30  上午8:59 上午
     */
    @WebListener
    public class SessionListener implements HttpSessionListener, ServletContextListener {
    
    
        /**
         * ServletContext 初始化的时候调用该方法,初始化用户人数为 0
         *
         * @param sce
         */
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            ServletContext servletContext = sce.getServletContext();
            servletContext.setAttribute("userCounter", new AtomicInteger());
        }
    
        /**
         * Session 会话被创建的时候,表示有新的用户访问网站,故而使用人数加一
         *
         * @param se
         */
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            HttpSession session = se.getSession();
            ServletContext servletContext = session.getServletContext();
            AtomicInteger userCounter = (AtomicInteger) servletContext.getAttribute("userCounter");
            int userCount = userCounter.incrementAndGet();
            System.out.println("new user welcome current user is :" + userCount);
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            HttpSession session = se.getSession();
            ServletContext servletContext = session.getServletContext();
            AtomicInteger userCounter = (AtomicInteger) servletContext.getAttribute("userCounter");
            int userCount = userCounter.decrementAndGet();
            System.out.println("has user leave current user is :" + userCount);
        }
    }
    

    HttpSessionAttributeListener

    当HttpSession中有添加,删除或者替换属性的时候就会被调用

    • void attributeAdded(HttpSessionBindingEvent event);

    • void attributeRemoved(HttpSessionBindingEvent event);

    • void attributeReplaced(HttpSessionBindingEvent event);

      由于 HttpSessionBindingEvent 是 HttpSessionEvent的子类,因此还可以在 HttpSessionAttributeListener 类中查到受影响的 HttpSession

    HttpSessionActivationListener:

    在分布式环境中,多个Servlet 容器会配置成可伸缩的,为了节约内存,Servlet容器可以对session属性进行迁移或者序列化。一般来说,当内存比较低时,相对较少访问的对象可以序列化到备用存储设备中,这样,Servlet容器就能够注意到哪些Session属性的类实现了HttpSessionActivationListener接口。

    这个接口中定义了两个方法:

    • void sessionDidActivate(HttpSessionEvent event);

    • void sessionWillPassivate(HttpSessionEvent event);

      包含这个对象的HttpSession一旦被激活(Activate),就会调用sessionDidActivate 方法。Servlet 容器传递给该方法的HttpSessionEvent 能够获取到刚刚激活的 HttpSession。

      当包含该监听器的HttpSession 即将被钝化(Passivate)时,会调用sessionWillPassivate方法。

    HttpSessionBindingListener

    当 HttpSessionBindingListener绑定到HttpSession,或者取消绑定时,都会收到通知。如果一个类香知道什么时候绑定或者取消绑定到HttpSession上,那么这个类要实现HttpSessionBindingListener接口,然后将它的实例保存为session 属性,它就可以自动更新。再比如,一旦HttpSessionBindingListener与HttpSession取消绑定,它的实现类就可以释放占用的资源。

    实例如下:

    package cn.com.yuns.listener;
    
    import lombok.Data;
    
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.HttpSessionBindingEvent;
    import javax.servlet.http.HttpSessionBindingListener;
    
    /**
     * @author wsq
     * @version Product.java  2020/7/30  上午11:13 上午
     */
    @WebListener
    @Data
    public class Product implements HttpSessionBindingListener {
    
        private String id;
    
        private String name;
    
        private double price;
    
        /**
         * 绑定时调用该方法
         *
         * @param event
         */
        @Override
        public void valueBound(HttpSessionBindingEvent event) {
            String attributeName = event.getName();
            System.out.println(attributeName + " valueBound");
        }
    
        /**
         * 解绑时调用该方法
         *
         * @param event
         */
        @Override
        public void valueUnbound(HttpSessionBindingEvent event) {
            String attributeName = event.getName();
            System.out.println(attributeName + " valueUnbound");
        }
    }
    

    ServletRequest监听器:

    在ServletRequest 级别上有三个监听器接口:ServletRequestListener,ServletRequestAttributeListener,和AsyncListener。

    ServletRequestListener对ServletRequest的创建和销毁做出响应。在Servlet容器中是通过池来重用ServletRequest的,创建ServletRequest花费的时间相当于从池中获取它的时间,ServletRequest销毁时间则相当于它返回到池中的时间。

    ServletRequestListener 接口定义了如下两个方法:

    • void requestInitialized(ServletRequestEvent event);

    • void requestDestroyed(ServletRequestEvent event);

      创建或从池中取出 ServletRequest 时会调用 requestInitialized方法,ServletRequest被销毁或返回池中时会调用 requestDestroyed 方法

      ServletRequestEvent 参数对象中定义了 获取 ServletRequest的方法,此外还定义了返回ServletContext的方法。

    ServletRequestAttributeListener

    当在ServletRequest中添加,删除或者替换某个属性的时候,会调用 ServletRequestAttributeListener ;该接口定义了三个方法:

    • void attributeAdded(ServletRequestAttributeEvent event);

    • void attributeRemoved(ServletRequestAttributeEvent event);

    • void attributeReplaced(ServletRequestAttributeEvent event);

    相关文章

      网友评论

          本文标题:监听器

          本文链接:https://www.haomeiwen.com/subject/tgjrrktx.html