概述
Servlet API提供了一系列的事件和事件监听器接口。上层的servlet/JSP应用能够通过调用这些API进行事件驱动的开发。这里监听的所有事件都继承自java.uitl.Event对象。监听器接口可以分为三类:ServletContext、HttpSession、ServletRequest。
监听器接口和注册
监听器接口主要在javax.servlet和javax.servlet.http包中,有以下接口:
- javax.servlet.ServletContextListener:它能够响应ServletContext生命周期事件,它提供了ServletContext创建之后和ServletContext关闭之前的会被调用的方法。
- javax.servlet.ServletContextAttributeListener:它能够响应ServletContext范围的属性添加、删除、替换事件。
- javax.servlet.http.HttpSessionListener:它能够响应HttpSession的创建、超时和失效事件。
- javax.servlet.http.HttpSessionAttributeListener:它能响应HttpSession范围的属性添加、删除、替换事件。
- javax.servlet.http.HttpSessionActivationListener:它在一个HttpSession激活或失效时被调用。
- javax.servlet.http.HttpSessionBindingListener:可以实现这个接口来保存HttpSession范围的属性。当有属性从HttpSession添加或删除时,HttpSessionBindingListener接口能够做出响应。
- javax.servlet.ServletRequestListener:它能够响应一个ServletRequest的创建或删除。
- javax.servlet.ServletRequestAttributeListener:它能响应ServletRequest范围的属性值添加、删除、修改事件。
- javax.servlet.AsyncListener:一个用于异步操作的监听器。
编写一个监听器,只需要写一个Java类来实现对应的监听器接口就可以看了。在Servlet3.0和Servlet3.1中提供了两种注册监听器的方法。第一种是使用WebListener注解,例如:
@WebListener
public class ListenerClass implements ListenerInterface {
}
第二种方法是在部署描述文档中添加一个listener元素。
<listener>
<listener-class>fully-qualified listener class</listener-class>
</listener>
你可以在一个应用中添加多个监听器。
Servlet Context 监听器
ServletContext的监听器接口有两个:ServletContextListener和ServletContextAttributeListener。
ServletContextListener
ServletContextListener能对ServletContext的创建和销毁做出响应。当ServletContext初始化时,容器会掉调用所有注册的ServletContextListeners的contextInitialized方法。该方法如下:
void contextInitialized(ServletContextEvent event);
当ServletContext将要销毁时,容器会调用所有注册的ServletContextListeners的contextDestroyed方法。该方法如下:
void contextDestroyed(ServletContextEvent event);
contextInitialized方法和contextDestroyed方法都会从容器获取到一个ServletContextEvent。javax.servlet.ServletContextEvent是一个java.util.EventObject的子类,它定义了一个访问ServletContext的getServletContext方法:
ServletContext getServletContext();
通过这个方法能够轻松获取到ServletContext。
@WebListener
public class AppListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
Map<String, String> countries = new HashMap<>();
countries.put("ca", "Canada");
countries.put("us", "United States");
servletContext.setAttribute("countries", countries);
}
}
ServletContextAttributeListener
当一个ServletContext范围的属性被添加、删除或者替换时,ServletContextAttributeListener接口的实现类会接收到消息。这个接口定义了如下三个方法:
void attributeAdded(ServletContextAttributeEvent event);
void attributeRemoved(ServletContextAttributeEvent event);
void attributeReplaced(ServletContextAttributeEvent event);
attributeAdded方法在一个ServletContext范围属性被添加时被容器调用。attributeRemoved方法在一个ServletContext范围属性被删除时被容器调用。而attributeReplaced方法在一个ServletContext范围属性被新的替换时被容器调用。
这三个方法都能获取到一个ServletConextAttributeEvent对象,通过这个对象可以后期属性的名称和值。
ServletContextAttributeEvent类继承自ServletContextAttribue,并且增加了下面两个方法,分别用于获取该属性的名称和值:
java.lang.String getName();
java.lang.Object getValue();
Session Listeners
一共有4个HttpSession相关的监听器接口:HttpSessionListener,HttpSessionActivationListener,HttpSessionAttributeListener和HttpSessionBindingListener。这四个接口都在javax.servlet.http包中。
HttpSessionListener
当一个HttpSession创建或者销毁时,容器都会通知所有的HttpSessionListener监听器,HttpSessionListener接口有两个方法:SessionCreated和sessionDestroyed:
void sessionCreated(HttpSessionEvent event);
void sessionDestroyed(HttpSessionEvent event);
这两个方法都可以接收到一个继承与java.util.Event的HttpSessionEvent对象。可以通过调用HttpSessionEvent对象的getSession方法来获取当前的HttpSession。getSession方法如下:
HttpSession getSession();
下面的示例是一个HttpSessionListener监听器。这个监听器来统计HtttpSession的数量。它使用了一个AtomiInteger对象来统计,并且将这个对象保存成ServletContext范围的属性。每当有一个HttpSession被创建时,这个AtomicInteger对象都会加一。每当有一个HttpSession被销毁时,这个AtomicInteger对象就会减一。所以这个对象会保存着当前存活的HttpSession数量。这里使用了AtomicInteger来代替Integer类型是为了保证能同步进行加减的操作。
package com.study.servletstudy;
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;
/**
* @Description : Session监听器
* @Version : V1.0.0
* @Date : 2021/11/30 21:20
*/
@WebListener
public class SessionListener implements HttpSessionListener, ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("userCount", new AtomicInteger());
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
ServletContext servletContext = session.getServletContext();
AtomicInteger userCounter = (AtomicInteger) servletContext.getAttribute("userCount");
int userCount = userCounter.incrementAndGet();
System.out.println("userCount incremented to :" + userCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
ServletContext servletContext = session.getServletContext();
AtomicInteger userCounter = (AtomicInteger) servletContext.getAttribute("userCount");
int userCount = userCounter.decrementAndGet();
System.out.println("userCount decremented to :" + userCount);
}
}
sessionCreated方法在每个HttpSession创建时被调用。
sessionDestroyed方法会在HttpSession销毁之前被调用。
浏览器调用URL:http://localhost:8080/servletStudy/
控制台打印如下信息:
userCount incremented to :1
用同一个浏览器再次访问这个URL并不会改变userCounter,因为这属于同一个HttpSession。使用不同的浏览器访问才能增加userCounter的值。
如果你所有时间等待HttpSession过期的话,在控制台也能看到HttpSession销毁时打印的信息。
HttpSessionAttributeListener
HttpSessionAttributeListener接口和ServletContextAttributeListener类似,它响应的是HttpSession范围属性的添加、删除和替换。
HttpSessionAttributeListener接口有一下方法:
void attributeAdded(HttpSessionBindingEvent event);
void attributeRemoved(HttpSessionBindingEvent event);
void attributeReplaced(HttpSessionBindingEvent event);
attributeAdded方法在一个HttpSession范围属性被添加时被容器调用。attributeRemoved方法在一个HttpSession范围属性被删除时被容器调用。而attributeReplaced方法在一个HttpSession范围属性被新的替换时被容器调用。
这三个方法都能获取到一个HttpSessionBindingEvent的对象,通过对象可以获取获取属性的名称和值:
java.lang.String getName();
java.lang.Object getValue();
由于HttpSessionBindingEvent是HttpSessionEvent的子类,因此也可以在HttpSessionAttributeListener实现类中获得HttpSession。
HttpSessionActivationListener
在分布式环境下,会用多个容器来进行负载均衡,有可能需要将session保存起来,在容器之间传递。
例如当一个容器内存不足时,会把很少用到的对象转存到其他容器上。这时候,容器就会通知所有HttpSessionActivationListener接口的实现类。
HttpSessionActivationListener接口有两个方法:
// 激活
void sessionDidActivate(HttpSessionEvent event);
// 去激活
void sessionWillPassivate(HttpSessionEvent event);
当HttpSession被转移到其他容器之后,sessionDidActive方法会被调用。容器将一个HttpSessionEvent方法传递到方法里,可以从这个对象获得HttpSessiion。
当一个HttpSession将要失效时,容器会调用sessionWillPassivate方法。和sessionDidActivate方法一样,容器将一个HttpSessionEvent方法传递到方法里,可以从这个对象获得HttpSession。
HttpSessionBindingListener
当有属性绑定或者解绑定到HttpSession上时,HttpSessionBindingListener监听器会被调用,如果对HttpSession属性的绑定和解绑懂得感兴趣,就可以实现HttpSessionBindingListener来监听。例如可以在HttpSession属性绑定时更新状态,或者在属性解绑是释放资源。
HttpSessionBindingListener接口有两个方法:
void valueBound(HttpSessionBindingEvent event);
void valueUnBound(HttpSessionBindingEvent event);
ServletRequest Listeners
ServletRequest范围的监听器接口有三个:ServletRequestListener、ServletRequestAttributeListener和AsyncListener。
ServletRequestListener
ServletRequestListener监听器会对ServletRequest的创建和销毁事件进行响应。容器会通过一个池来存放并重复利用多个ServletRequest,ServletRequest的创建时从容器池里被分配出来的时刻开始,而它的销毁时刻是放回容器池里的时间。
ServletRequestListener接口有两个方法,requestInitialized和requestDestroyed:
void requestInitialized(ServletRequestEvent event);
void requestDestroyed(ServletRequestEvent event);
当一个 ServletRequest创建(从容器池里取出)时,requestInitialized方法会被调用,当ServletRequest销毁(被容器回收)时,requestDestroyed方法会被调用。这两个方法都会接收到一个ServletRequestEvent对象,可以通过使用这个对象的getServletRequest方法来获取ServletRequest对象:
ServletRequest getServletRequest();
另外,ServletRequestEvent接口也提供了一个getServletContext方法来获取ServletContext,如下所示:
ServletContext getServletContext();
ServletRequstAttributeListener
当一个ServletRequest范围的属性被添加、删除或替换时,ServletRequestAttributeListener接口会被调用。ServletRequestAttributeListener接口提供了三个方法:attributeAdded、attributeReplaced、attributeRemoved。
void attributeAdded(ServletRequestAttributeEvent event);
void attributeRemoved(ServletRequestAttributeEvent event);
void attributeReplaced(ServletRequestAttributeEvent event);
这些方法都可以获得一个继承自ServletRequestEvent的ServletRequestAttributeEvent对象。通过ServletRequestAttributeEvent类提供的getName和getValue方法可以访问到属性的名称和值:
java.lang.String getName();
java.lang.Object getValue();
小结
Servlet API提供了多个监听器类型。这些监听器可以分层三类:application范围、session范围和request范围。监听器的使用很简单,可以通过两种方式注册监听器:在实现类上使用@WebListener注解或者在部署描述文件中增加listener元素。
Servlet3.0新增了一个监听器接口javax.servlet.AsycListener。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100245.html