文章目录
1 什么是监听器
监听器就是监视web应用里面的某些对象的变化而进行一些处理操作。
监听器的一些相关概念:
- 事件源:就是被监视的对象。
- 监听器对象:监视事件源的对象。
- 注册(绑定):将监听器与事件源进行绑定,当事件源对象发生改变时就会触发监听器对象。
- 事件:监听器监听到事件源发生改变时的响应行为。
- 事件对象:在监听器对象里获得事件源对象。
2 监听器的分类
JavaEE规范中有8个监听器接口,用于监听不同的WEB对象。具体的分类如下表所示:

- 绑定和解绑:
HttpSessionBindingListener
- 钝化和活化:
HttpSessionActivationListener
3 监听域对象创建和销毁
使用方法:
- 创建一个对象实现对应的监听器的接口。
- 重写监听器接口的抽象方法。
- 配置(注册)监听器。(web.xml或注解)
3.1 ServletContextListener
此监听器是监听ServletContext对象的创建和销毁,使用方法是创建一个类实现该监听器接口,重写里面的抽象方法,还需在web.xml文件中配置监听器或者使用注解配置,否则不起作用。
public class MyServletContextListener implements ServletContextListener {
//监听ServletContext对象的创建
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象的创建啦");
}
//监听ServletContext对象的销毁
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象的销毁了");
}
}
配置文件使用web.xml配置,也可用注解配置。
<listener>
<listener-class>com.gsgb.create.MyServletContextListener</listener-class>
</listener>
- 当服务器启动时创建了ServletContext对象,此时监听器监听到了ServletContext对象的创建,就会调用contextInitialized方法,在控制台打印。
- 当服务器正常关闭时,当监听器监听到了ServletContext对象销毁了,在销毁之前调用contextDestroyed方法。
SerVletContextEvent对象:
从上面的代码中,我们可以看到两个方法里面的参数都是ServletContextEvent对象,它是一个事件对象,可以通过它获取被监听的对象,即事件源。具体方法如下:
ServletContext getServletContext(); //获取事件源
ServletContextEvent类继承EventObject类,EventObject类里面有个通用的方法也可以获得事件源对象,只不过返回值是Object类型的,具体如下:
Object getSource();//获取事件源
其实getServletContext()方法的内部也是调用它的父类的getSource()方法,方法源码如下:
public ServletContext getServletContext() {
return (ServletContext) super.getSource();
}
ServletContextListener的作用
- 通过监听ServletContext对象的创建,我们可以做一些初始化的工作,如初始化一些对象或数据,加载数据库驱动和连接池的初始化等。
- 加载一些初始化的配置文件 ,如spring的配置文件。
- 任务调度(定时器)——Timer/TimerTask。
了解了上面的内容,我们来写一个模拟银行计息的例子,要求服务器启动后每天晚上12点开始计息。
public class MyServletContextListener implements ServletContextListener {
//监听ServletContext对象的创建
public void contextInitialized(ServletContextEvent sce) {
//获取服务器开启的当天晚上12点的日期
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date date = cal.getTime();//此处已经获取到当天晚上12点的Date对象
//创建Timer计时器对象
Timer timer = new Timer();
//通过Timer对象开启指定时间开始以固定的时间开始计息
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//模拟银行计息
System.out.println("银行计息一次...");
}
}, date, 24*60*60*1000);
}
//监听ServletContext对象的销毁
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象的销毁了");
}
}
<listener>
<listener-class>com.gsgb.bank.MyServletContextListener</listener-class>
</listener>
3.2 HttpSessionListener
HttpSessionListener的用法其实也和ServletContextListener差不多,只是他们监听的对象不同而已,此监听器是用来监听session对象的创建和销毁。
监听器代码:
public class MyHttpSessionListener implements HttpSessionListener {
//监听session对象的创建
public void sessionCreated(HttpSessionEvent se) {
System.out.println("session对象的创建了");
}
//监听session对象的销毁
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session对象的销毁了");
}
}
配置文件代码
<listener>
<listener-class>com.gsgb.create.MyHttpSessionListener</listener-class>
</listener>
获取session对象代码
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("获取session前");
//获取或创建一个session
HttpSession session = request.getSession();
System.out.println("获取session后");
//延迟5s手动销毁session
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
session.invalidate();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
当我们访问获取session的资源时,在创建session的时候会触发监听器,当我们等待5s销毁的时候也会触发监听器。代码的运行结果如下图所示:

HttpSessionEvent对象:
该对象也是事件对象,可以通过它获取被它监听的对象:
- 第一种方式:
HttpSession session = se.getSession();
- 第二种方式:此对象和SerVletContextEvent对象一样也是EventObject的子类,故此可以用父类的方法,
HttpSession session = (HttpSession)se.getSource();
HttpSessionListener的作用
在服务器开启后因为客户访问资源会产生多个session对象,因此每次客户访问的时候就会产生或获取一个session对象,每产生一个session对象就会触发监听器。基于这个原理我们可以再监听创建session的方法里计数来获得网站的访问量。
3.3 ServletRequsetListener
此监听器是用来监听request对象的创建和销毁。
public class MyServletRequestListener implements ServletRequestListener{
@Override
//监听request对象的创建
public void requestInitialized(ServletRequestEvent sre) {
ServletContext servletContext = sre.getServletContext();
ServletRequest servletRequest = sre.getServletRequest();
Object source = sre.getSource();
System.out.println("request对象创建了");
}
@Override
//监听request对象的销毁
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("request对象销毁了");
}
}
<listener>
<listener-class>com.gsgb.create.MyServletRequestListener</listener-class>
</listener>
ServletRequestEvent对象
该事件对象也是EventObject类的子类,能够获取当前监听的request对象,还能获取ServletContext对象。
ServletContext servletContext = sre.getServletContext();
ServletRequest servletRequest = sre.getServletRequest();
Object source = sre.getSource();
4 监听域对象的属性变化
使用方法:
- 创建一个对象实现对应的监听器的接口。
- 重写监听器接口的抽象方法。
- 配置(注册)监听器。(web.xml或注解)
4.1 ServletContextAttibuteListener
public class MyServletContextAttibuteListener implements ServletContextAttributeListener{
@Override
//监听域内增加属性,获取增加的属性键值
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("域中的键值对:"+scae.getName()+" = "+scae.getValue());
System.out.println("域中添加数据了");
}
@Override
//监听域内删除属性,获取的是删除前的值
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("域中的键值对:"+scae.getName()+" = "+scae.getValue());
System.out.println("域中数据被删除了");
}
@Override
//监听域内修改属性,获取的是修改前的值
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("域中的键值对:"+scae.getName()+" = "+scae.getValue());
System.out.println("域中数据修改了");
}
}
<listener>
<listener-class>com.gsgb.attr.MyServletContextAttibuteListener</listener-class>
</listener>
添加数据的Servlet
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext context = this.getServletContext();
//向域对象设置值
context.setAttribute("game", "DOTA2");
//向域对象修改值
context.setAttribute("game", "LOL");
//删除域对象的值
context.removeAttribute("game");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
当我们访问向域中添加数据的资源时,当域中数据增删改操作时就会触发监听器。所以上代码的结果是:
域中的键值对:game = DOTA2
域中添加数据了
域中的键值对:game = DOTA2
域中数据修改了
域中的键值对:game = LOL
域中数据被删除了
注意:监听器的attributeReplaced()方法里面通过事件对象获取的键和值是修改前的键和值
4.2 HttpSessionAttributeListener
此监听器和ServletContextAttibuteListener监听器用法差不多。略。
4.3 ServletRequestAriibuteListenr
此监听器和ServletContextAttibuteListener监听器用法差不多。略。
5 两个特殊的监听器
两个特殊的监听器分别是HttpSessionBindingListener绑定解绑HttpSessionActivationListener钝化活化。这两个监听器的作用是监听即将要存储到session域中的对象的状态。有四种状态:
- 绑定状态:就一个对象被放到session域中。
- 解绑状态:就是这个对象从session域中移除了。
- 钝化状态:是将session内存中的对象持久化(序列化)到磁盘。
- 活化状态:就是将磁盘上的对象再次恢复到session内存中。
5.1 HttpSessionBindingListener
此监听器是针对对象的绑定和解绑的。此监听器的使用方法如下:
- 创建要监听的JavaBean对象,实现HttpSessionBindingListener接口。
- 重写接口里的抽象方法。
注意:此监听器不需要配置。
JavaBean对象
public class User implements HttpSessionBindingListener{
private String name;
private int age;
public User() {}
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
//代码过长,我省略了get和set
@Override
//监听对象被绑定
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("哎呀,我被绑了");
}
@Override
//监听对象解绑
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("哈哈,我解绑了");
}
}
测试代码
public class TestUserServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取session对象
HttpSession session = request.getSession();
//创建JavaBean对象
User user = new User("zhangsab", 23);
//将JavaBean存到Session域中
session.setAttribute("user", user);
//将JavaBean从Session域中删除
session.removeAttribute("user");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
执行结果
哎呀,我被绑了
user
哈哈,我解绑了
user
HttpSessionBindingEvent事件
HttpSessionBindingEvent类是HttpSessionEvent类的子类,他有如下的方法:
public String getName();//获取存储到session域的对象的名字,即键
public Object getValue() //获取存储到session域的对象,即值
public HttpSession getSession()//获取session对象(从父类继承的方法)
HttpSessionBindingListener和HttpSessionAttributeListener对比
- HttpSessionAttributeListener需要在web.xml或注解注册,可以监听在session域中的任意对象。
- HttpSessionBindingListener不需要注册,只能监听当前JavaBean对象。
5.2 HttpSessionActivationListener
此监听器是监听存到session域中对象的钝化与活化的,钝化就是将session中的对象存到磁盘上,而活化就是将该对象恢复到内存中。
我们为什么要钝化和活化呢,因为如果用户过多而且他长时间没有操作,我们还不能销毁session,防止删除了用户正在操作的内容,这样的话就会给服务器增加压力,所以钝化和活化的出现是十分有必要的,在用户没有操作的时候,我们就给他的session域里面的对象序列化到硬盘上,当用户再次操作网站的时候,就反序列化到内存中就可以了,这样就可以减小服务器的压力了。
使用此监听器的步骤如下:
- 创建一个JavaBean,实现HttpSessionActivationListener接口和Serializable序列化接口。
- 重写接口里的抽象方法。
注意:此监听器不需要配置
package com.itheima.domain;
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
public class User implements HttpSessionActivationListener,Serializable{
private String name;
private int age;
public User() {
}
//代码过长,我省略了get和set
@Override
//监听对象钝化
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("我是User对象,我被钝化了");
}
@Override
//监听对象活化
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("我是User对象,我被活化了");
}
}
注意钝化和活化的前提是服务器正常关闭和session存在,假如过期了等问题导致session没有了是不存在钝化和活化的。
JavaBean我们已经写好了,那么存储在session域中的JavaBean对象何时钝化何时活化呢,假如不进行任何配置的话,默认是下面的情况:
- 钝化:服务器正常关闭时就会钝化。
- 活化:服务器启动后对象活化,我们就可与存取数据了。
当对象被钝化时,会在tomcat路径\work\Catalina\localhost\项目名
里面创建一个SESSION.ser文件。

上面是默认的情况,那么我们该怎么利用配置文件来配置该对象何时钝化呢。我们需要写一个xml配置文件即可。
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- maxIdleSwap:session中的对象多长时间不使用就钝化 -->
<!-- directory:序列化后文件存放路径 -->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="OutSession" />
</Manager>
</Context>
当我们使用了配置文件后,序列化后的文件就会输出到我们知道的文件夹里。
如:Tomcat路径\work\Catalina\localhost\项目路径\OutSession
。