JavaWeb—监听器Listener

1.简介

Listener是Servlet的监听器,Servlet 监听器用于监听一些重要事件的发生,监听器对象在事情发生前、发生后可以做一些必要的处理。

JavaWeb里面的listener是通过观察者设计模式进行实现的。

观察者模式又叫发布订阅模式或者监听器模式。在该模式中有两个角色:观察者和被观察者(通常也叫做主题)。观察者在主题里面注册自己感兴趣的事件,当这个事件发生时,主题会通过回调接口的方式通知观察者。

举个生活中的例子:订阅报纸。任何一个家庭或个人都可以向报社订阅报纸。这里报社就是“主题”,家庭就是“观察者”。比如家庭需要订阅明天早晨的报纸,这个就是“事件”。到了第二天早晨,报纸生产出来了,这个就是“事件发生”。当事件发生时,送报员将报纸送到家庭的信箱里面,这里的信箱就是“回调接口”。

对于JavaWeb里面的监听器,Servlet规范定义了一些列的Listener接口类,通过接口类的方式将事件暴露给应用程序,应用程序如果想监听其感兴趣的事件,那么不必去直接注册对应的事件,而是编写自己的listener实现相应的接口类,并将自己的listener注册到servlet容器。当程序关心的事件发生时,servlet容器会通知listener,回调listener里面的方法。这里自定义的listener就是观察者,servlet容器就是主题。

 

2.分类

现在我们分析下,servlet规范为我们定义了哪些事件。更准确的说是定义了哪些监听接口。下面的介绍都是以servlet3.0规范为准。

servlet3.0为我们提供了8个监听器接口,按照它们的作用域来划分的话可以分为三类:

1.servlet上下文相关监听接口:

  • ServletContextListener
  • ServletContextAttributeListener

2.http session相关监听接口:

  • HttpSessionListener
  • HttpSessionActivationListener
  • HttpSessionAttributeListener
  • HttpSessionBindingListener

3.servlet request相关监听接口:

  • ServletRequestListener
  • ServletRequestAttributeListener

 

3.Java编写Listener实例

Listener编写分为两步:

  1. 编写自己的listener,实现特定的Listener接口
  2. 在web.xml里面注册自己的listener(也可以通过注解的方式,道理是一样的)

ListenerDemo.java(这里继承ServletContextListener接口):

public class ListenerDemo implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("----------ServletContextListener.contextInitialized-----------");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("----------ServletContextListener.contextDestroyed----------");
    }
}

web.xml:

<listener>
    <listener-class>com.xzh.ListenerDemo</listener-class>
</listener>

效果图:

注意:结果中可以看到listener比filter先执行。

 

4.源码分析

4.1 ServletContextListener

public interface ServletContextListener extends EventListener {
    void contextInitialized(ServletContextEvent var1);

    void contextDestroyed(ServletContextEvent var1);
}

servlet上下文监听器接口,对应着两个事件:servlet上下文初始化事件和servlet上下文即将关闭事件。

当web应用初始化的时候,servlet容器会构造ServletContextEven实例,并回调contextInitialize方法。当servlet上下文即将关闭时,一般是关闭服务器之前,servlet容器会构造ServletContextEven实例,并回调contextDestroyed方法。这里需要注意的是,contextDestroyed方法的执行会在所有的servlet和filter执行完destroy方法之后。

4.2 ServletContextAttributeListener

public interface ServletContextAttributeListener extends EventListener {
    void attributeAdded(ServletContextAttributeEvent var1);

    void attributeRemoved(ServletContextAttributeEvent var1);

    void attributeReplaced(ServletContextAttributeEvent var1);
}

当servlet上文属性发生增、删、改的时候,servlet容器构造ServletContextAttributeEvent事件对象,分别回调attributeAdded、attributeRemoved、attributeReplaced方法。

这里需要注意的是attributeReplaced方法,当属性的值被替换的时候回调。这个时候如果调用ServletContextAttributeEvent.getValue()方法返回的是替换之前的属性值。

4.3 HttpSessionListener

public interface HttpSessionListener extends EventListener {
    void sessionCreated(HttpSessionEvent var1);

    void sessionDestroyed(HttpSessionEvent var1);
}

当session被创建和销毁的时候,servlet容器构造HttpSessionEvent事件对象,并回调sessionCreated和sessionDestroyed方法。

4.4 HttpSessionActivationListener

public interface HttpSessionActivationListener extends EventListener {
    void sessionWillPassivate(HttpSessionEvent var1);

    void sessionDidActivate(HttpSessionEvent var1);
}

当session将要钝化或已被激活时,servlet容器构造HttpSessionEvent事件对象,回调sessionWillPassivate和sessionDidActivate方法。

这里解释下钝化和激活:钝化是指服务器内存不够了或者session的活动超时时间到了,把最近不活动的session序列化到磁盘。激活是指某个钝化的session又被访问了,从磁盘将session反序列化到内存。

这里可以看出要想钝化和激活,首先session得可序列化和反序列化。同时我们在编程过程中,session尽量用String、Integer等简单的对象,尽量不要用list、map等集合。3.5

4.5 HttpSessionAttributeListener

public interface HttpSessionAttributeListener extends EventListener {
    void attributeAdded(HttpSessionBindingEvent var1);

    void attributeRemoved(HttpSessionBindingEvent var1);

    void attributeReplaced(HttpSessionBindingEvent var1);
}

当session属性发生增、删、改的时候,servlet容器构造HttpSessionBindingEvent事件对象,分别回调attributeAdded、attributeRemoved、attributeReplaced方法。

这里需要注意的是attributeReplaced方法,当属性的值被替换的时候回调。这个时候如果调用ServletContextAttributeEvent.getValue()方法返回的是替换之前的属性值。

当调用session的invalidate方法或者session失效时,也会回调attributeRemoved方法。

4.6 HttpSessionBindingListener

public interface HttpSessionBindingListener extends EventListener {
    void valueBound(HttpSessionBindingEvent var1);

    void valueUnbound(HttpSessionBindingEvent var1);
}

这个监听器也是监听session的属性变化。当session属性发生增和删,也就是属性值绑定和属性值解绑的时候,servlet容器构造HttpSessionBindingEvent事件对象,分别回调valueBound、valueUnbound方法。

这么一看和HttpSessionAttributeListener没什么区别,其实不是这样。两者有个本质的区别就是事件触发的条件。

当session的属性有任何的变化,servlet容器都会通知HttpSessionAttributeListener。但是对于HttpSessionBindingListener,只有当绑定或解绑的属性值是监听器的实例时,servlet容器才会通知。

4.7 ServletRequestListener

public interface ServletRequestListener extends EventListener {
    void requestDestroyed(ServletRequestEvent var1);

    void requestInitialized(ServletRequestEvent var1);
}

当请求初始化或者销毁时,即客户端请求进入web应用(进入servlet或者第一个filter)或web应用返回响应给客户端(退出servlet或者第一个filter)。servlet容器构造ServletRequestEvent实例,回调requestInitialized和requestDestroyed方法。

4.8 ServletRequestAttributeListener

public interface ServletRequestAttributeListener extends EventListener {
    void attributeAdded(ServletRequestAttributeEvent var1);

    void attributeRemoved(ServletRequestAttributeEvent var1);

    void attributeReplaced(ServletRequestAttributeEvent var1);
}

当请求的属性发生增、删、改的时候,servlet容器构造ServletRequestAttributeEvent事件对象,分别回调attributeAdded、attributeRemoved、attributeReplaced方法。

这里需要注意的是attributeReplaced方法,当属性的值被替换的时候回调。这个时候如果调用ServletRequestAttributeEvent.getValue()方法返回的是替换之前的属性值。

 

 

 

参考:

JavaWeb——Listener

java常用的Listener分类

 

posted @ 2017-08-30 10:53  大象踢足球  阅读(386)  评论(0编辑  收藏  举报