监听器-Servlets(三)

概述

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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

融极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值