10-监听器

# 介绍

监听器设计三个组件:事件源,事件对象,事件监听器

三者关系为:事件监听器监听事件源的方法,当触发事件源的事件时,事件监听器就调用对应的方法,同时将该事件对象作为参数传递给该方法。

事件源可以通过事件对象获得。

事件源需要注册监听器对象(简单来说,就是告诉监听器你要监听哪个事件源)。

Servlet监听器

介绍

  • 它们是一组来自Servlet规范下的接口,共有8个
  • Http服务器没有提供实现类,需要开发人员手动实现
  • 监听器接口用于监控作用域对象生命周期变化时刻和作用域对象共享数据变化时刻

在Servlet规范中定义了多种类型监听器,他们用于监听的事件源分别为:

  • ServletContext:全局作用域对象
  • HttpSession:会话作用域对象
  • ServletRequest:请求作用域对象

对应的监听器对象分别为ServletContextListener,HttpSessionListener和ServletRequestListener。

不过和其他事件监听器不同的是,Servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员需要在web.xml文件中使用标签配置好监听器。

监听类接口实现类开发规范

共分三步:

  • 根据监听实际情况,选择对应监听器接口进行实现
  • 重写监听器接口声明(即监听事件处理方法)
  • 在web.xml文件中将监听器接口实现类注册到Http服务器

监听器监听对象的创建和销毁

HttpSessionListener、ServletContextListener、ServletRequestListener分别监控着Session、
Context、Request对象的创建和销毁。

每个接口都定义了两个方法,分为为对象创建和销毁的方法

20200813204102

监听器可以监听到ServletContext的初始化和销毁,Session的创建。(服务器关闭,不代表Session被销毁,Session创建在服务器内存中,所以看不到Session被销毁)

监听对象属性变化

ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener
分别监听着Context、Session、Request对象属性的变化。

三个接口都定义了三个方法来处理被监听对象中的属性增加,删除和替换的事件,同一个事件在这三个接口中对应方法名称完全相同,只是接受参数类型不同。

image-20200814111213577

只演示Context对象,其他都可依此类推。

监听器对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Listener implements ServletContextAttributeListener {

public Listener() {

}

@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("Context对象增加了属性");
}

@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("Context对象删除了属性");

}

@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("Context对象更新了属性");
}
}

用于测试Servlet对象:

1
2
3
4
5
6
7
8
9
10
11
public class TestServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("name", "哈哈哈ce");
servletContext.setAttribute("name", "哈哈哈哈");
servletContext.removeAttribute("name");
}
}

测试结果为:

image-20200814112021198

监听Session内的对象

除了上述六种Listener,还有两种Listener监听Session内的对象,分别是HttpSessionBindingListener和HttpSessionActivationListener,实现这两个接口不需要在web.xml文件中注册。

  • 实现HttpSessionBindingListener接口,JavaBean对象可以感知自己被绑定到Session中和从Session中删除的事件(和HttpSessionAttributeListener的作用差不多)
  • 实现HttpSessionActivationListener接口,JavaBean对象可以感知自己被活化和钝化的事件(当服务器关闭的时候,会将Session的内容保存在硬盘上,称为钝化;服务器开启时,会将Session的内容在硬盘上重新加载,称为活化)

image-20200814141343471

如果想要测试Session的硬化和钝化,需要修改Tomcat配置。在META-INF目录下的context.xml文件中添加代码:

1
2
3
4
5
6
7
<Context>
<Manager className="org.apache.catalina.session.PersistentManager"
maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore"
directory="zhongfucheng"/>
</Manager>
</Context>

监听器的简单应用

加快程序运行速度

例如在之前做的在线考试管理系统中,用户注册需要连接数据库,插入数据,其中Connection的创建和销毁非常消耗时间,所以需要在服务器启动时就创建一批Connection,即数据库连接池,那么程序如何知道Tomcat服务器什么时候启动呢,就可以使用全局作用域对象ServletContext对象的监听器,其中的初始化方法,服务器在启动时,一定会创建ServletContext对象,就可以编写监听器对象方法,在这个方法中,创建一批Connection对象,即可加快程序运行速度

统计网站在线人数

在网站中使用Session来标识用户是否登录,如果登录了,就在Session域中保存相应属性,如果没有登录,那么Session属性就为空。

要统计网站在线人数,应该这样做:监听是否有新的Session创建了,如果有,那么在线人数就+1,这个在线人数是针对整个网站的,所以需要使用Context全局作用域对象来保存

所以思路就是:

  • 监听Session是否被创建,如果被创建了,那么在Context的域对象的值就加1
  • 如果Session从内存中被移除了,那么在Context的域对象中的值-1

监听器代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Listener implements HttpSessionListener {

public Listener() {
}

@Override
public void sessionCreated(HttpSessionEvent se) {

ServletContext servletContext = se.getSession().getServletContext();

Integer num = (Integer) servletContext.getAttribute("num");

if(num == null) {
servletContext.setAttribute("num", 1);
} else {
num++;
servletContext.setAttribute("num", num);
}

}

@Override
public void sessionDestroyed(HttpSessionEvent se) {

ServletContext servletContext = se.getSession().getServletContext();

Integer num = (Integer) servletContext.getAttribute("num");

if(num == null) {
servletContext.setAttribute("num", 1);
} else {
num--;
servletContext.setAttribute("num", num);
}
}
}

10-监听器
https://zhaoquaner.github.io/2022/05/11/JavaWeb/Servlet/11-监听器/
更新于
2022年5月22日
许可协议