一、什么是监听器
监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext、HttpSession和ServletRequest等域对象的创建和销毁事件,它还可以监听域对象的属性发生修改的事件,可以在事件发生前或者发生后做一些必要的处理。
在Servlet中要创建监听器类首先需要新建一个类并继承相应的监听器接口,实现接口中定义的方法,然后在web.xml文件中注册相应的监听器即可。如果一个web.xml文件中注册了多个监听器,则监听器的启动顺序按照在web.xml中的注册顺序启动。如果一个web.xml文件中同时定义了监听器、过滤器和Servlet,那么web容器会先加载监听器、再加载过滤器最后加载Servlet。
二、监听器的分类
按照监听的事件可以将监听器划分为以下三类:
1、监听域对象自身的创建和销毁的事件监听器;
2、监听域对象中属性的增加和删除的事件监听器;
3、监听绑定到HttpSession域中某个对象状态的事件监听器。
下面分别来分析这三类监听器。
1、监听域对象自身的创建和销毁的事件监听器
这一类监听器主要监听ServletContext、HttpSession和ServletRequest这三个域对象创建和销毁的事件,要实现这一类监听器,需要继承ServletContextListener、HttpSessionListener或者ServletRequestListener接口,分别来对这三个域对象进行分析。
(1)首先是继承ServletContextListener,这一类监听器主要监听应用程序环境发生的事件,而要继承ServletContextListener,就需要实现该接口中的contextInitialized和contextDestroyed方法,简单地说就是启动服务器创建应用程序上下文时和关闭服务器销毁程序上下文时执行的操作。可以参考下面的实例:
package com.imooc.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* Application Lifecycle Listener implementation class MyServletContextListener
*
*/
public class MyServletContextListener implements ServletContextListener {
/**
* Default constructor.
*/
public MyServletContextListener() {
}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("contextDestroyed");
}
/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent arg0) {
String name = arg0.getServletContext().getInitParameter("name");
System.out.println("contextInitialized : name=" + name);
}
}
这个例子中在服务器启动时,运行contextInitialized方法,可以通过ServletContextEvent来获取服务器启动的初始参数,这些初始参数都是在web.xml文件中配置的。当服务器停止时,会执行监听器的contextDestroyed方法,进行资源的回收等操作。定义了监听器之后,就可以在web.xml中注册监听器了,注册内容如下,同时还定义了初始化参数。
<listener>
<listener-class>com.imooc.listener.MyServletContextListener</listener-class>
</listener>
<context-param>
<param-name>name</param-name>
<param-value>imooc</param-value>
</context-param>
这时启动服务器,观察启动日志,会发现打印出如下的日志,获取到了初始化参数name的值并打印出来,说明监听器已经启动了。
……
八月 23, 2016 8:38:19 下午 org.apache.jasper.servlet.TldScanner scanJars
信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
contextInitialized : name=imooc
八月 23, 2016 8:38:19 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8080"]
……
再停止服务器,会发现打印了执行监听器里destroy方法的内容。
……
八月 23, 2016 8:40:58 下午 org.apache.catalina.core.StandardService stopInternal
信息: Stopping service Catalina
contextDestroyed
八月 23, 2016 8:40:58 下午 org.apache.coyote.AbstractProtocol stop
信息: Stopping ProtocolHandler ["http-nio-8080"]
……
(2)接下来看继承HttpSessionListener的监听器,这一类监听器监听的是用户会话对象的创建和销毁事件,定义如下的监听器,在创建和销毁会话对象时将输出一句话。
package com.imooc.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Application Lifecycle Listener implementation class MySessionListener
*
*/
public class MySessionListener implements HttpSessionListener {
/**
* Default constructor.
*/
public MySessionListener() {
}
/**
* @see HttpSessionListener#sessionCreated(HttpSessionEvent)
*/
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("sessionCreated");
}
/**
* @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
*/
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("sessionDestroyed");
}
}
接着需要在web.xml中注册相应的监听器。
<listener>
<listener-class>com.imooc.listener.MySessionListener</listener-c