8.2 ServletContext监听器 8.2.1 ServletContextListener

8.2 ServletContext监听器

ServletContext简介

  • ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个ServletContext对象。
  • ServletContext对象是一个全局的储存信息的空间,项目启动时该对象就存在了,项目关闭时才会释放该对象。

ServletContext的监听接口

ServletContext的监听器接口有两个:ServletContextListenerServletContextAttributeListener

8.2.1 ServletContextListener

Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent事件,该事件由ServletContextListener来处理。
也就是说:ServletContextListener能对ServletContext的创建和销毁做出响应。

响应ServletContext的创建

ServletContext初始化时,容器会调用所有注册了ServletContextListeners接口的实例的contextInitialized方法。该方法如下:

1
void contextInitialized(ServletContextEvent event)

响应ServletContext的销毁

ServletContext将要销毁时,容器会调用所有注册了ServletContextListeners接口的实例的contextDestroyed方法。该方法如下:

1
void contextDestroyed(ServletContextEvent event)

contextInitialized方法和contextDestroyed方法都会从容器获取到一个ServletContextEventjavax.servlet.ServletContextEvent是一个java.util.EventObject的子类,它定义了一个访问ServletContextgetServletContext方法:

1
ServletContext getServletContext()

通过这个方法能够轻松地获取到ServletContext

实例

这个项目名为:app08a

下面的AppListener.java类实现了ServletContextListener接口,它在ServletContext刚创建时,将一个保存国家编码和国家名的Map放置到ServletContext中。

AppListener.java

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
package app08a.listener;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
//@WebListener注解表示当前类是一个事件监听器
@WebListener
public class AppListener
implements
ServletContextListener
{
@Override
public void contextDestroyed(ServletContextEvent sce)
{}
// 在项目载入服务器的时候被调用
@Override
public void contextInitialized(ServletContextEvent sce)
{
// 通过ServletContextEvent参数的getServletContext方法
// 获取ServletContext对象
ServletContext servletContext = sce.getServletContext();
//创建一个Map
Map<String,String> countries =
new HashMap<String,String>();
//添加数据到Map中
countries.put("ca", "Canada");
countries.put("us", "United States");
//设置该map对象为servletContext的`countries`属性
servletContext.setAttribute("countries", countries);
System.out.println("ServletContextListener."
+ "contextInitialized方法被调用");
}
}

在实现的contextInitialized方法中。先通过调用getServletContext方法从容器获得ServletContext实例,然后创建了一个Map用于保存国家编码和国家名,再将这个Map放置到ServletContext里。
在实际开发中,往往是把数据库里的数据放置到ServletContext里。

下面的countries.jsp用到了这个监听器。

countries.jsp页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<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>

countries.jsp页面使用了JSTLforEach标签来迭代读取名为countriesmap里的数据。
JSTL的使用步骤请看这篇文章

运行效果

运行这个项目,查看控制台可以看到项目启动的时候就调用了contextInitialized方法了如下图所示:
这里有一张图片

可以通过下面的URL来访问这个JSP页面:
http://localhost:8080/app08a/countries.jsp
浏览器显示效果如下图所示:
这里有一张图片

小结

  • 每个web项目启动时,容器会为该Web项目创建对应一个对应的ServletContext对象.
  • 关闭该Web项目时,容器会销毁该Web项目对应的ServletContext对象.
  • ServletContext对象的创建和销毁会触发ServletContextEvent事件
  • ServletContextListeners接口的实例可以处理ServletContextEvent事件。
    • ServletContextListeners接口的实例的contextInitialized方法在ServletContext对象创建时候被调用。
    • ServletContextListeners接口的实例的contextDestroyed方法在ServletContext对象销毁的时候被调用