监听器
为了能够在 Servlet 应用程序中进行事件驱动编程,Servlet API 提供了一整套事件类和监听器接口。所有事件类均源自java.util.Event,并且监听器在以下三个不同级别中均可用:ServletContext,HttpSession,ServletRequest.
监听器接口和注册
ServletContextListener
ServletContextAttributeListener
HttpSessionListener
HttpSessionActivationListener
HttpSessionAttributeListener
HttpSessionBindingListener
ServletRequestListener
ServletRequestAttributeListener
AsyncListener。
注册监听器有两种方式:注解(@WebListener)/在部署描述符(web.xml)中配置
<listener>
<listener-class>
</listener-class>
</listener>
ServletContext 监听器
在ServletContext 级别上有两个监听器接口:ServletContextListener,ServletContextAttributeListener
ServletContextListener:
ServletContextListener会对 ServletContext 的初始化和解构做出响应。ServletContext被初始化的时候,Servlet容器会在所有已注册的ServletContextListener中调用 contextInitialized 方法,方法签名如下:
-
void contextInitialized(ServletContextEvent event)
当ServletContext要被解构和销毁时,Servlet容器会在所有已注册的ServletContextListener中调用 contextDestroyed 方法,方法签名如下:
-
void contextDestroyed(ServletContextEvent event)
ServletContextEvent是 java.util.EventObject 类的派生类。其中定义了方法:
ServletContext getServletContext()
实例如下:
JSTL 依赖引入:
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
package cn.com.yuns.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.util.HashMap;
import java.util.Map;
/**
* 以注解的方式申明监听器
*
* @author wsq
* @version AppListener.java 2020/7/30 上午8:32 上午
*/
@WebListener
public class AppListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
Map<String, String> countries = new HashMap<>();
countries.put("ca", "China");
countries.put("jp", "Japan");
countries.put("am", "American");
servletContext.setAttribute("countries", countries);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
<%--
Created by IntelliJ IDEA.
User: wsq
Date: 2020/7/30
Time: 8:36 上午
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<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>
ServletContextAttributeListener:
每当ServletContext 中添加,删除或替换了某个属性时,所有注册的实现了ServletContextAttributeListener的监听器都会收到通知:
下面是这个监听器接口定义的三个方法:
-
void attributeAdded(ServletContextAttributeEvent event);
-
void attributeRemoved(ServletContextAttributeEvent event);
-
void attributeReplaced(ServletContextAttributeEvent event);
在ServletContext 中,添加,删除,替换某个属性时,上上面的三个方法就会被分别调用。ServletContextAttributeEvent派生自 ServletContextAttribute
Session监听器
与HttpSession 有关的监听器接口有四个:HttpSessionListener,HttpSessionActivationListener,HttpSessionAttributeListener,HttpSessionBindingListener。
HttpSessionListener:
当有HttpSession 被创建或者销毁的时候,Servlet 容器就会调用所有已经注册的HttpSessionListener。
HttpSessionListener:定义了两个方法:
-
void sessionCteated(HttpSessionEvent event)
-
void sessionDestroyed(HttpSessionEvent event)
方法参数 HttpSessionEvent 定义了一个方法:
HttpSession getSession();
实例如下:
package cn.com.yuns.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author wsq
* @version SessionListener.java 2020/7/30 上午8:59 上午
*/
@WebListener
public class SessionListener implements HttpSessionListener, ServletContextListener {
/**
* ServletContext 初始化的时候调用该方法,初始化用户人数为 0
*
* @param sce
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("userCounter", new AtomicInteger());
}
/**
* Session 会话被创建的时候,表示有新的用户访问网站,故而使用人数加一
*
* @param se
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
ServletContext servletContext = session.getServletContext();
AtomicInteger userCounter = (AtomicInteger) servletContext.getAttribute("userCounter");
int userCount = userCounter.incrementAndGet();
System.out.println("new user welcome current user is :" + userCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
ServletContext servletContext = session.getServletContext();
AtomicInteger userCounter = (AtomicInteger) servletContext.getAttribute("userCounter");
int userCount = userCounter.decrementAndGet();
System.out.println("has user leave current user is :" + userCount);
}
}
HttpSessionAttributeListener
当HttpSession中有添加,删除或者替换属性的时候就会被调用
-
void attributeAdded(HttpSessionBindingEvent event);
-
void attributeRemoved(HttpSessionBindingEvent event);
-
void attributeReplaced(HttpSessionBindingEvent event);
由于 HttpSessionBindingEvent 是 HttpSessionEvent的子类,因此还可以在 HttpSessionAttributeListener 类中查到受影响的 HttpSession
HttpSessionActivationListener:
在分布式环境中,多个Servlet 容器会配置成可伸缩的,为了节约内存,Servlet容器可以对session属性进行迁移或者序列化。一般来说,当内存比较低时,相对较少访问的对象可以序列化到备用存储设备中,这样,Servlet容器就能够注意到哪些Session属性的类实现了HttpSessionActivationListener接口。
这个接口中定义了两个方法:
-
void sessionDidActivate(HttpSessionEvent event);
-
void sessionWillPassivate(HttpSessionEvent event);
包含这个对象的HttpSession一旦被激活(Activate),就会调用sessionDidActivate 方法。Servlet 容器传递给该方法的HttpSessionEvent 能够获取到刚刚激活的 HttpSession。
当包含该监听器的HttpSession 即将被钝化(Passivate)时,会调用sessionWillPassivate方法。
HttpSessionBindingListener
当 HttpSessionBindingListener绑定到HttpSession,或者取消绑定时,都会收到通知。如果一个类香知道什么时候绑定或者取消绑定到HttpSession上,那么这个类要实现HttpSessionBindingListener接口,然后将它的实例保存为session 属性,它就可以自动更新。再比如,一旦HttpSessionBindingListener与HttpSession取消绑定,它的实现类就可以释放占用的资源。
实例如下:
package cn.com.yuns.listener;
import lombok.Data;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/**
* @author wsq
* @version Product.java 2020/7/30 上午11:13 上午
*/
@WebListener
@Data
public class Product implements HttpSessionBindingListener {
private String id;
private String name;
private double price;
/**
* 绑定时调用该方法
*
* @param event
*/
@Override
public void valueBound(HttpSessionBindingEvent event) {
String attributeName = event.getName();
System.out.println(attributeName + " valueBound");
}
/**
* 解绑时调用该方法
*
* @param event
*/
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
String attributeName = event.getName();
System.out.println(attributeName + " valueUnbound");
}
}
ServletRequest监听器:
在ServletRequest 级别上有三个监听器接口:ServletRequestListener,ServletRequestAttributeListener,和AsyncListener。
ServletRequestListener对ServletRequest的创建和销毁做出响应。在Servlet容器中是通过池来重用ServletRequest的,创建ServletRequest花费的时间相当于从池中获取它的时间,ServletRequest销毁时间则相当于它返回到池中的时间。
ServletRequestListener 接口定义了如下两个方法:
-
void requestInitialized(ServletRequestEvent event);
-
void requestDestroyed(ServletRequestEvent event);
创建或从池中取出 ServletRequest 时会调用 requestInitialized方法,ServletRequest被销毁或返回池中时会调用 requestDestroyed 方法
ServletRequestEvent 参数对象中定义了 获取 ServletRequest的方法,此外还定义了返回ServletContext的方法。
ServletRequestAttributeListener
当在ServletRequest中添加,删除或者替换某个属性的时候,会调用 ServletRequestAttributeListener ;该接口定义了三个方法:
-
void attributeAdded(ServletRequestAttributeEvent event);
-
void attributeRemoved(ServletRequestAttributeEvent event);
-
void attributeReplaced(ServletRequestAttributeEvent event);
网友评论