Java Web——过滤器 & 监听器

目录

[1. Filter & 过滤器](#1. Filter & 过滤器)

[1.1. 过滤器概述](#1.1. 过滤器概述)

[1.2. 过滤器的使用](#1.2. 过滤器的使用)

[1.3. 过滤器生命周期](#1.3. 过滤器生命周期)

[1.4. 过滤器链的使用](#1.4. 过滤器链的使用)

[1.5. 注解方式配置过滤器](#1.5. 注解方式配置过滤器)

[2. Listener & 监听器](#2. Listener & 监听器)

[2.1. 监听器概述](#2.1. 监听器概述)

[2.2. Java Web的监听器](#2.2. Java Web的监听器)

[2.2.1. 常用监听器](#2.2.1. 常用监听器)

[2.2.1.1. ServletContextListener监听器](#2.2.1.1. ServletContextListener监听器)

[2.2.1.2. ServletContextAttributeListener监听器](#2.2.1.2. ServletContextAttributeListener监听器)

[2.2.2. 其他监听器](#2.2.2. 其他监听器)

[2.2.2.1. session域监听器](#2.2.2.1. session域监听器)

[2.2.2.2. HttpSessionListener 监听器](#2.2.2.2. HttpSessionListener 监听器)

[2.2.2.3. HttpSessionAttributeListener 监听器](#2.2.2.3. HttpSessionAttributeListener 监听器)

[2.2.2.4. request域监听器](#2.2.2.4. request域监听器)

[2.2.2.5. ServletRequestListener 监听器](#2.2.2.5. ServletRequestListener 监听器)

[2.2.2.6. ServletRequestAttributeListener 监听器](#2.2.2.6. ServletRequestAttributeListener 监听器)

[2.2.3. session域的两个特殊监听器](#2.2.3. session域的两个特殊监听器)

[2.2.3.1. HttpSessionBindingListener 监听器](#2.2.3.1. HttpSessionBindingListener 监听器)

[2.2.3.2. HttpSessionActivationListener 监听器](#2.2.3.2. HttpSessionActivationListener 监听器)


1. Filter & 过滤器

1.1. 过滤器概述

Filter是Java Web开发中的一种技术,它可以对目标资源的请求进行过滤。简单来说,Filter就像是一个前置处理器或者拦截器,它会在目标资源被请求之前执行,对请求进行一定的处理或者拦截。

  • Filter接口是Filter的开发规范,所有开发的Filter都需要实现这个接口。当一个请求到达Filter时,容器会先创建一个HttpServletRequest和HttpServletResponse对象,然后调用Filter的doFilter方法。
  • doFilter方法决定了一个请求是否可以继续执行。如果doFilter方法允许请求继续,那么请求将会被转发到目标资源。如果doFilter方法拒绝了请求,那么请求就会在这个Filter中停止,由Filter自己对请求做出响应。
  • 除了对请求进行过滤,Filter也可以在目标资源响应之前对响应进行再次处理。因此,Filter不仅可以用于对请求的过滤,也可以用于对响应的处理。
  • Filter是GOF(设计模式)中责任链模式的典型案例。责任链模式是指多个对象形成一个处理请求的链条,每个对象都有机会处理请求,直到有一个对象处理了请求为止。
  • Filter的常用应用非常广泛,包括但不限于登录权限检查、解决网站乱码、过滤敏感字符、日志记录、性能分析等。这些应用都是通过Filter技术实现的。

举个例子:

生活举例中,公司前台、停车场安保和地铁验票闸机都是Filter的典型应用。它们都可以对进入的人员或者车辆进行审核和过滤。如果符合条件,就放行;如果不符合条件,就拒绝进入。同时,它们也可以在人员或者车辆离开时进行再次审核和收费。


Filter工作原理图解:


Filter接口API:

从IDEA上面的Filter.java上扒下来的源码,也就三个抽象方法:

  • i**nit(FilterConfig filterConfig):**这是过滤器初始化时调用的方法。在这个方法中,可以设置过滤器的一些配置信息,如参数等。默认的实现是不执行任何操作。

  • **doFilter(ServletRequest request, ServletResponse response, FilterChain chain):**这是过滤器的主要工作方法。每次客户端请求资源时,都会调用此方法。在这个方法中,可以根据需要修改请求和响应对象,并决定是否将请求传递给下一个过滤器或目标资源。这通常涉及检查请求,可能修改请求或响应,然后调用chain.doFilter()来继续过滤器链,最后可能直接在响应上设置头信息。

  • **destroy():**这是过滤器被移除服务时调用的方法。在这个方法中,可以进行一些清理工作,例如释放资源,确保所有持久状态与内存中的当前状态同步。默认的实现同样不执行任何操作。


1.2. 过滤器的使用

目标:开发一个日志记录过滤器

  • 用户请求到达目标资源之前,记录用户的请求资源路径
  • 响应之前记录本次请求目标资源运算的耗时
  • 可以选择将日志记录进入文件,为了方便测试,这里将日志直接在控制台打印

LoggingFilter.java 过滤器

package filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class LoggingFilter implements Filter { //实现Filter接口
    public void init(FilterConfig config) throws ServletException {
        System.out.println("以启用登录过滤器~");
    }

    private final SimpleDateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 参数父转子
        HttpServletRequest request =(HttpServletRequest)  servletRequest;
        HttpServletResponse  response =(HttpServletResponse)  servletResponse;
        // 拼接日志文本
        String requestURI = request.getRequestURI();
        String time = dateFormat.format(new Date());
        String beforeLogging =requestURI+"在"+time+"被请求了";
        // 打印日志
        System.out.println(beforeLogging);
        // 获取系统时间
        long t1 = System.currentTimeMillis();
        // 放行请求
        filterChain.doFilter(request,response);
        // 获取系统时间
        long t2 = System.currentTimeMillis();
        //  拼接日志文本
        String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";
        // 打印日志
        System.out.println(afterLogging);
    }

    @Override
    public void destroy() {
        System.out.println("以销毁登录过滤器~");
    }
}

配置web.xml

不配置web.xml就是普通的java类,无法实现filter过滤器的功能

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--配置过滤器-->
    <filter> 
        <filter-name>loggingFilter</filter-name> <!--过滤器名称-->
        <filter-class>filter.LoggingFilter</filter-class> <!--过滤器类名-->
    </filter>
    
    <filter-mapping> 
        <filter-name>loggingFilter</filter-name> <!--过滤器名称-->
        <url-pattern>/*</url-pattern> <!--过滤器拦截的url,/* 表示对所有资源进行过滤-->
    </filter-mapping>

</web-app>

说明:

ServletA.java

package servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/servletA")
public class ServletA extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp){
        // 处理器请求
        System.out.println("servletA处理请求的方法,耗时10毫秒");
        // 模拟处理请求耗时
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

ServletB.java

package servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/servletB")
public class ServletB extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp){
        // 处理器请求
        System.out.println("servletB处理请求的方法,耗时15毫秒");
        // 模拟处理请求耗时
        try {
            Thread.sleep(15);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

启动服务器


1.3. 过滤器生命周期

Filter在Web项目中是一个重要的组件,其生命周期与Servlet有些类似,但也有一些区别。

  1. **创建(Creation):**Filter对象在系统启动时就会被创建。不像Servlet需要配置load-on-startup参数才能实现系统启动时立即创建,Filter的创建是默认行为,系统启动时就会立即创建Filter对象。
  2. **初始化(Initialization):**在Filter对象创建后,会调用其init方法进行初始化。这个过程通常会接收一个FilterConfig对象作为参数,通过这个对象可以获取到Filter的配置信息。
  3. **执行(Execution):**初始化完成后,Filter就可以开始执行其任务。在Web应用中,Filter通常被用来执行一些通用的操作,如日志记录、数据压缩、认证授权等。Filter的执行顺序是根据其在web.xml中的配置顺序来决定的。
  4. **销毁(Destroy):**当Web应用关闭或重启时,Filter的生命周期结束,会调用其destroy方法进行资源清理。

|--------|--------------------------------------------------------------------------------------------------------|----------|----------|
| 阶段 | 对应方法 | 执行时机 | 执行次数 |
| 创建对象 | 构造器 | web应用启动时 | 1 |
| 初始化方法 | void init(FilterConfig filterConfig) | 构造完毕 | 1 |
| 过滤请求 | void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) | 每次请求 | 多次 |
| 销毁 | default void destroy() | web应用关闭时 | 1次 |


1.4. 过滤器链的使用

过滤器链概述:

在一个Web项目中,可以定义多个过滤器(Filter)。这些过滤器可以同时存在,并且可以对同一个资源进行过滤操作。这些过滤器按照一定的顺序形成一个工作链,这个工作链被称为过滤器链(Filter Chain)。

  • **过滤器链中的过滤器的顺序是由filter-mapping的配置顺序决定的。**在web.xml文件中,我们可以配置多个filter-mapping,每个filter-mapping定义了一个过滤器及其对应的匹配规则。这些过滤器按照filter-mapping的顺序依次执行。
  • 每个过滤器都有其特定的过滤范围。对于同一个资源来说,可能需要经过多个过滤器的过滤。因此,过滤器链中的过滤器个数可能会因为资源的不同而有所差异。
  • 另外,如果某个过滤器是使用ServletName进行匹配规则的配置,那么这个过滤器的执行优先级相对较低。这意味着,当一个请求到达时,过滤器链会先执行那些使用ServletName进行匹配规则配置的过滤器,然后再执行其他过滤器。


示例:

如果定义了三个过滤器Filter1、Filter2、Filter3,执行顺序也是1、2、3

这里Filter的代码就不举例了,关键在于web.xml的写法

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
  
  	<filter>
        <filter-name>filter1</filter-name>
        <filter-class>filters.Filter1</filter-class>
    </filter>

    <filter>
        <filter-name>filter2</filter-name>
        <filter-class>filters.Filter2</filter-class>
    </filter>

    <filter>
        <filter-name>filter3</filter-name>
        <filter-class>filters.Filter3</filter-class>
    </filter>

    <!--filter-mapping的顺序决定了过滤器的工作顺序-->
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <url-pattern>/servletC</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>filter2</filter-name>
        <url-pattern>/servletC</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>filter3</filter-name>
        <url-pattern>/servletC</url-pattern>
    </filter-mapping>
</web-app>

1.5. 注解方式配置过滤器

注解方式配置过滤器是指在Java Web应用程序中使用注解来定义和配置过滤器。

和servlet注解类似,通过注解,可以省略web.xml配置文件,直接在Java类中声明过滤器。


Filter注解源码(还是从IDEA上面复制下来的):

package javax.servlet.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.servlet.DispatcherType;

/**
 * Annotation used to declare a servlet filter.
 *
 * <p>This annotation is processed by the container at deployment time,
 * and the corresponding filter applied to the specified URL patterns,
 * servlets, and dispatcher types.
 * 
 * @see javax.servlet.Filter
 *
 * @since Servlet 3.0
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {

    /**
     * The description of the filter
     * 
     * @return the description of the filter
     */
    String description() default "";

    /**
     * The display name of the filter
     *
     * @return the display name of the filter
     */
    String displayName() default "";

    /**
     * The init parameters of the filter
     *
     * @return the init parameters of the filter
     */
    WebInitParam[] initParams() default {};
    
    /**
     * The name of the filter
     *
     * @return the name of the filter
     */
    String filterName() default "";
    
    /**
     * The small-icon of the filter
     *
     * @return the small-icon of the filter
     */
    String smallIcon() default "";

    /**
     * The large-icon of the filter
     *
     * @return the large-icon of the filter
     */
    String largeIcon() default "";

    /**
     * The names of the servlets to which the filter applies.
     *
     * @return the names of the servlets to which the filter applies
     */
    String[] servletNames() default {};
    
    /**
     * The URL patterns to which the filter applies
     * The default value is an empty array.
     *
     * @return the URL patterns to which the filter applies
     */
    String[] value() default {};

    /**
     * The URL patterns to which the filter applies
     *
     * @return the URL patterns to which the filter applies
     */
    String[] urlPatterns() default {};

    /**
     * The dispatcher types to which the filter applies
     *
     * @return the dispatcher types to which the filter applies
     */
    DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};
    
    /**
     * Declares whether the filter supports asynchronous operation mode.
     *
     * @return {@code true} if the filter supports asynchronous operation mode
     * @see javax.servlet.ServletRequest#startAsync
     * @see javax.servlet.ServletRequest#startAsync(ServletRequest,
     * ServletResponse)
     */
    boolean asyncSupported() default false;

}

对源码进行分析:

  1. @Target({ElementType.TYPE}): 这个注解只能应用于类级别。
  2. @Retention(RetentionPolicy.RUNTIME): 这个注解将在运行时保留,在运行时可以被反射API读取。
  3. @Documented: 这个注解会被包含在用户的JavaDoc中。
  4. String description() default "";: 返回过滤器的描述,默认为空字符串。
  5. String displayName() default "";: 返回过滤器的显示名称,默认为空字符串。
  6. WebInitParam[] initParams() default {};: 返回过滤器的初始化参数,默认为一个空数组。
  7. String filterName() default "";: 返回过滤器的名字,默认为空字符串。
  8. String smallIcon() default "";: 返回过滤器的小图标,默认为空字符串。
  9. String largeIcon() default "";: 返回过滤器的大图标,默认为空字符串。
  10. String[] servletNames() default {};: 返回过滤器应用到的Servlet名字,默认为一个空数组。
  11. String[] value() default {};: 和urlPatterns()方法相同,返回过滤器应用到的URL模式,默认为一个空数组。
  12. String[] urlPatterns() default {};: 返回过滤器应用到的URL模式,默认为一个空数组。
  13. DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};: 返回过滤器应用到的调度类型,默认为REQUEST。
  14. boolean asyncSupported() default false;: 声明过滤器是否支持异步操作模式,默认为false。

代码示例:

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "MyFilter", urlPatterns = {"/welcome"})
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作,如读取配置参数等
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Before processing request");

        // 调用下一个过滤器或servlet
        chain.doFilter(request, response);

        System.out.println("After processing request");
    }

    @Override
    public void destroy() {
        // 清理资源等
    }
}

2. Listener & 监听器

2.1. 监听器概述

Listener 监听器是 JavaWeb 应用程序中的一种组件,它是 Servlet、Filter 和 Listener 这三个组件之一。Listener 是 Java EE 规范中的一部分,它是一个接口,用于监听特定事件或变化,并在触发时执行相应的任务。

监听器的作用是监听特定的对象或事件,例如对象的创建/销毁或属性变化等,当这些事件发生时,监听器会触发对应的方法来完成相应的任务。

有八个常用的监听器

其中最常用的是 ServletContextListenerServletContextAttributeListener


举个例子:

监听器可以比喻为"报警器"。比如我们在家里安装的烟雾报警器,当烟雾达到一定浓度时,报警器就会发出警报,提醒我们可能有火灾隐患。这个报警器就是"监听器",它监听的是烟雾浓度这个事件。当烟雾浓度达到设定阈值时,它就会触发警报。

在JavaWeb应用程序中,监听器也是类似的原理。比如ServletContextListener,它监听的是ServletContext对象的变化。当ServletContext对象创建或销毁时,ServletContextListener就会触发对应的方法来完成相应的任务。


监听器分类:

根据所监听的对象和事件的不同,可以将监听器大致分为以下几类:

  1. 按监听的对象划分:
  • Application域监听器:这类监听器监听的是ServletContext对象,其中包括ServletContextListener和ServletContextAttributeListener。ServletContextListener用于监听ServletContext对象的创建和销毁事件,而ServletContextAttributeListener则用于监听ServletContext对象属性的变化。
  • Session域监听器:这类监听器监听的是HttpSession对象,其中包括HttpSessionListener、HttpSessionAttributeListener和HttpSessionBindingListener。HttpSessionListener用于监听HttpSession对象的创建和销毁事件,HttpSessionAttributeListener用于监听HttpSession对象属性的变化,而HttpSessionBindingListener则用于监听HttpSession对象绑定和解绑事件。
  • Request域监听器:这类监听器监听的是ServletRequest对象,其中包括ServletRequestListener和ServletRequestAttributeListener。ServletRequestListener用于监听ServletRequest对象的创建和销毁事件,ServletRequestAttributeListener用于监听ServletRequest对象属性的变化。

  1. 按监听的事件划分:
  • 域对象的创建和销毁监听器:这类监听器包括ServletContextListener、HttpSessionListener和ServletRequestListener,它们分别用于监听ServletContext、HttpSession和ServletRequest对象的创建和销毁事件。
  • **域对象数据增删改事件监听器:**这类监听器包括ServletContextAttributeListener、HttpSessionAttributeListener和ServletRequestAttributeListener,它们分别用于监听ServletContext、HttpSession和ServletRequest对象属性的变化事件。
  • **其他监听器:**这类监听器包括HttpSessionBindingListener和HttpSessionActivationListener等,它们分别用于监听HttpSession对象绑定和解绑事件以及激活事件等。

2.2. Java Web的监听器

2.2.1. 常用监听器

在Java Web监听器中,常用的监听器是

ServletContextListenerServletContextAttributeListener

**ServletContextListener: 这个接口提供了一个监听器,可以监听ServletContext对象的创建和销毁事件。**当Web应用程序启动时,会创建一个ServletContext对象,而在应用程序关闭时,该对象将被销毁。通过实现ServletContextListener接口,可以在这两个关键时刻执行特定的操作。例如,可以在ServletContext对象创建时初始化一些全局变量或执行其他必要的设置,或在对象销毁时进行资源清理。

**ServletContextAttributeListener: 这个接口提供了一个监听器,可以监听ServletContext属性(即在ServletContext对象中存储的属性)的添加和移除事件。**可以通过实现这个接口来监听特定属性的添加或移除操作,并在这些操作发生时执行特定的操作。例如,当某个属性被添加到ServletContext时,可以进行一些初始化操作;当某个属性被移除时,可以执行一些清理操作。


2.2.1.1. ServletContextListener监听器

ServletContextListener监听器:监听ServletContext对象的创建与销毁

ServletContextListener本身就是一个接口,继承EventListener接口


相关方法:

|---------------------------------------------|---------------------|
| 方法名 | 作用 |
| contextInitialized(ServletContextEvent sce) | ServletContext创建时调用 |
| contextDestroyed(ServletContextEvent sce) | ServletContext销毁时调用 |

ServletContextListener的源码,一个继承与EventListener的接口

package javax.servlet;

import java.util.EventListener;

public interface ServletContextListener extends EventListener {

    /**
     * Receives notification that the web application initialization
     * process is starting.
     *
     * <p>All ServletContextListeners are notified of context
     * initialization before any filters or servlets in the web
     * application are initialized.
     *
     * @param sce the ServletContextEvent containing the ServletContext
     * that is being initialized
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void contextInitialized(ServletContextEvent sce) {}

    /**
     * Receives notification that the ServletContext is about to be
     * shut down.
     *
     * <p>All servlets and filters will have been destroyed before any
     * ServletContextListeners are notified of context
     * destruction.
     *
     * @param sce the ServletContextEvent containing the ServletContext
     * that is being destroyed
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void contextDestroyed(ServletContextEvent sce) {}
}

代码举例:

ServletContextListenerA.java

package listener;

import javax.servlet.ServletContextListener;

public class ServletContextListenerA implements ServletContextListener {

    @Override
    public void contextInitialized(javax.servlet.ServletContextEvent sce) {
        System.out.println("ServletContextListenerA被创建");
    }

    @Override
    public void contextDestroyed(javax.servlet.ServletContextEvent sce) {
        System.out.println("ServletContextListenerA已销毁");
    }
}

配置 web.xml

启动服务器:

停止服务器:

小总结:

  1. 当一个类实现了ServletContextListener接口,它就变成了一个监听器。ServletContextListener是Java Servlet API的一部分,它能够监听ServletContext的创建和销毁事件。
  2. 这个类可以监听的事件由它实现的监听接口决定。如果一个类实现了ServletContextListener,那么这个类就可以监听ServletContext的创建和销毁事件。也就是说,当web应用启动时,ServletContext对象被创建,以及当web应用关闭时,ServletContext对象被销毁,这些事件都可以被监听。
  3. ServletContextListenerA是一个实现了ServletContextListener接口的类,因此它也是一个监听器。当web应用启动时,会产生一个ServletContextEvent事件,这个事件会调用监听器的对应事件处理方法contextInitialized。同时,会传递一个事件对象给这个方法。
  4. 程序员可以通过这个事件对象,来获取需要的信息,然后再进行业务处理。例如,他们可以通过这个对象获取关于ServletContext的信息,以及关于事件类型和其他相关属性的信息。
  5. Tomcat知道这个监听器存在是因为我们需要在web.xml中配置它。在web.xml文件中,我们可以定义ServletContextListener,当Tomcat加载web应用时,它会读取这个文件并加载所有的ServletContextListener。这样,当web应用启动或关闭时,Tomcat就会调用这些监听器的事件处理方法。

总的来说,ServletContextListener是Java Servlet API的一部分,它允许我们监听web应用的生命周期事件。我们可以通过实现这个接口来创建自己的监听器,并在web.xml中配置它,以便Tomcat知道它的存在。


2.2.1.2. ServletContextAttributeListener监听器

ServletContextAttributeListener监听器:监听ServletContext中属性的添加、移除和修改

ServletContextAttributeListener本身也是一个接口,继承EventListener接口

相关方法:

|------------------------------------------------------|---------------------------|
| 方法名 | 作用 |
| attributeAdded(ServletContextAttributeEvent scab) | 向ServletContext中添加属性时调用 |
| attributeRemoved(ServletContextAttributeEvent scab) | 从ServletContext中移除属性时调用 |
| attributeReplaced(ServletContextAttributeEvent scab) | 当ServletContext中的属性被修改时调用 |

ServletContextAttributeListener的源码:

package javax.servlet;

import java.util.EventListener;

public interface ServletContextAttributeListener extends EventListener {

    /**
     * Receives notification that an attribute has been added to the
     * ServletContext.
     *
     * @param event the ServletContextAttributeEvent containing the
     * ServletContext to which the attribute was added, along with the
     * attribute name and value
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void attributeAdded(ServletContextAttributeEvent event) {}

    /**
     * Receives notification that an attribute has been removed
     * from the ServletContext.
     *
     * @param event the ServletContextAttributeEvent containing the
     * ServletContext from which the attribute was removed, along with
     * the attribute name and value
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void attributeRemoved(ServletContextAttributeEvent event) {}

    /*
     * Receives notification that an attribute has been replaced
     * in the ServletContext.
     *
     * @param event the ServletContextAttributeEvent containing the
     * ServletContext in which the attribute was replaced, along with
     * the attribute name and its old value
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void attributeReplaced(ServletContextAttributeEvent event) {}
}

代码举例:

ServletContextAttributeListener01.java

package listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class ServletContextAttributeListener01 implements ServletContextAttributeListener {

    @Override // 监听ServletContext添加属性
    public void attributeAdded(ServletContextAttributeEvent sce) {
        System.out.println("ServletContextAttributeListener01监听到了添加属性" +
                sce.getName() + "的值");
    }

    @Override // 监听ServletContext移除属性
    public void attributeRemoved(javax.servlet.ServletContextAttributeEvent sce) {
        System.out.println("ServletContextAttributeListener01监听到了移除属性" +
                sce.getName() + "的值");
    }

    @Override // 监听ServletContext替换属性
    public void attributeReplaced(javax.servlet.ServletContextAttributeEvent sce) {
        System.out.println("ServletContextAttributeListener01监听到了替换属性" +
                sce.getName() + "的值");
    }
    
}

ServletA.java

package servlet;

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/servletA") //这里servlet用的注解,不用在web.xml配置
public class ServletA extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp){

        //给ServletContext添加属性
        ServletContext servletContext = req.getServletContext();
        servletContext.setAttribute("name", "Tom");
        servletContext.setAttribute("name", "Jerry");
        servletContext.removeAttribute("name");

        System.out.println("ServletA处理完毕...");

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp){
        doPost(req, resp);
    }
}

配置web.xml

启动服务器


2.2.2. 其他监听器

除了ServletContextListener和ServletContextAttributeListener,其他的监听器用的比较少


2.2.2.1. session域监听器
2.2.2.2. HttpSessionListener 监听器

**作用:**HttpSessionListener 是一个监听器,用来监听 HTTP 会话的创建和销毁。

当一个 HTTP 会话被创建或销毁时,它就会触发相应的事件,我们可以编写代码来响应这些事件。

例如,在会话创建时,我们可以进行一些初始化操作;在会话销毁时,我们可以释放一些资源。这样,我们就可以在用户的状态变化时,做出相应的处理。

HttpSessionListener的源码:

package javax.servlet.http;

import java.util.EventListener;

public interface HttpSessionListener extends EventListener {
    
    /** 
     * Receives notification that a session has been created.
     *
     * @implSpec
     * The default implementation takes no action.
     *
     * @param se the HttpSessionEvent containing the session
     */
    default public void sessionCreated(HttpSessionEvent se) {}
    
    /** 
     * Receives notification that a session is about to be invalidated.
     *
     * @implSpec
     * The default implementation takes no action.
     *
     * @param se the HttpSessionEvent containing the session
     */
    default public void sessionDestroyed(HttpSessionEvent se) {}
}

相关方法:

|---------------------------------------|--------------|
| 方法名 | 作用 |
| sessionCreated(HttpSessionEvent se) | 创建session时调用 |
| sessionDestroyed(HttpSessionEvent se) | 销毁session时调用 |


2.2.2.3. HttpSessionAttributeListener 监听器

**作用:**HttpSessionAttributeListener 是一个用于监听 HTTP 会话属性变化的监听器。

这意味着,当会话中的属性发生添加、删除或修改时,这个监听器会接收到通知。

HttpSessionAttributeListener源码:

package javax.servlet.http;

import java.util.EventListener;

public interface HttpSessionAttributeListener extends EventListener {

    /**
     * Receives notification that an attribute has been added to a
     * session.
     *
     * @param event the HttpSessionBindingEvent containing the session
     * and the name and value of the attribute that was added
     */
    default public void attributeAdded(HttpSessionBindingEvent event) {}

    /**
     * Receives notification that an attribute has been removed from a
     * session.
     *
     * @param event the HttpSessionBindingEvent containing the session
     * and the name and value of the attribute that was removed
     */
    default public void attributeRemoved(HttpSessionBindingEvent event) {}

    /**
     * Receives notification that an attribute has been replaced in a
     * session.
     *
     * @param event the HttpSessionBindingEvent containing the session
     * and the name and (old) value of the attribute that was replaced
     */
    default public void attributeReplaced(HttpSessionBindingEvent event) {}

}

相关方法:

|--------------------------------------------------|---------------------|
| 方法名 | 作用 |
| attributeAdded(HttpSessionBindingEvent event) | 向HttpSession添加属性时调用 |
| attributeRemoved(HttpSessionBindingEvent event) | 向HttpSession移除属性时调用 |
| attributeReplaced(HttpSessionBindingEvent event) | 向HttpSession替换属性时调用 |


2.2.2.4. request域监听器
2.2.2.5. ServletRequestListener 监听器

**作用:**监听 Request 创建或销毁,即Request生命周期监听。

ServletRequestListener的源码:

package javax.servlet;

import java.util.EventListener;

public interface ServletRequestListener extends EventListener {

    /**
     * Receives notification that a ServletRequest is about to go out
     * of scope of the web application.
     *
     * @param sre the ServletRequestEvent containing the ServletRequest
     * and the ServletContext representing the web application
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void requestDestroyed(ServletRequestEvent sre) {}

    /**
     * Receives notification that a ServletRequest is about to come
     * into scope of the web application.
     *
     * @param sre the ServletRequestEvent containing the ServletRequest
     * and the ServletContext representing the web application
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void requestInitialized(ServletRequestEvent sre) {}
}

相关方法:

|---------------------------------------------|--------------|
| 方法名 | 作用 |
| requestDestroyed(ServletRequestEvent sre) | 创建request时调用 |
| requestInitialized(ServletRequestEvent sre) | 销毁request时调用 |


2.2.2.6. ServletRequestAttributeListener 监听器

**作用:**ServletRequestAttributeListener 监听器可以监听 ServletRequest 对象中的属性变化。当属性被添加、移除或替换时,这个监听器会收到通知并执行相应的操作。

ServletRequestAttributeListener 源码:

package javax.servlet;

import java.util.EventListener;

public interface ServletRequestAttributeListener extends EventListener {

    /**
     * Receives notification that an attribute has been added to the
     * ServletRequest.
     *
     * @param srae the ServletRequestAttributeEvent containing the 
     * ServletRequest and the name and value of the attribute that was
     * added
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void attributeAdded(ServletRequestAttributeEvent srae) {}

    /**
     * Receives notification that an attribute has been removed from the
     * ServletRequest.
     *
     * @param srae the ServletRequestAttributeEvent containing the 
     * ServletRequest and the name and value of the attribute that was
     * removed
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void attributeRemoved(ServletRequestAttributeEvent srae) {}

    /**
     * Receives notification that an attribute has been replaced on the
     * ServletRequest.
     *
     * @param srae the ServletRequestAttributeEvent containing the 
     * ServletRequest and the name and (old) value of the attribute
     * that was replaced
     *
     * @implSpec
     * The default implementation takes no action.
     */
    default public void attributeReplaced(ServletRequestAttributeEvent srae) {}
}

相关方法:

|------------------------------------------------------|-----------------|
| 方法名 | 作用 |
| attributeAdded(ServletRequestAttributeEvent srae) | 向Request添加属性时调用 |
| attributeRemoved(ServletRequestAttributeEvent srae) | 向Request移除属性时调用 |
| attributeReplaced(ServletRequestAttributeEvent srae) | 向Request替换属性时调用 |


2.2.3. session域的两个特殊监听器

2.2.3.1. HttpSessionBindingListener 监听器

HttpSessionBindingListener 监听器也叫session绑定监听器

**作用:**HttpSessionBindingListener 监听 HttpSession 中对象的添加和移除,以确保数据的准确性和一致性。它可以帮助我们跟踪数据变化并触发相应操作。

HttpSessionBindingListener 监听器用于监听某个对象在 HttpSession 中的添加和移除操作。当该对象被添加到 HttpSession 中或从 HttpSession 中移除时,监听器会自动执行相应的操作。这个监听器通常用于管理在 HttpSession 中存储的数据,确保数据的一致性和准确性。

简单来说,它可以帮助我们跟踪 HttpSession 中数据的变化,并触发相应的操作。

HttpSessionBindingListener源码:

package javax.servlet.http;

import java.util.EventListener;

public interface HttpSessionBindingListener extends EventListener {

    /**
     *
     * Notifies the object that it is being bound to
     * a session and identifies the session.
     *
     * @implSpec
     * The default implementation takes no action.
     * 
     * @param event		the event that identifies the
     *				session 
     *
     * @see #valueUnbound
     *
     */ 
    default public void valueBound(HttpSessionBindingEvent event) {}

    /**
     *
     * Notifies the object that it is being unbound
     * from a session and identifies the session.
     *
     * @implSpec
     * The default implementation takes no action.
     *
     * @param event		the event that identifies
     *				the session 
     *	
     * @see #valueBound
     *
     */
    default public void valueUnbound(HttpSessionBindingEvent event) {}
}

相关方法:

|--------------------------------------------------|----------------------|
| 方法名 | 作用 |
| valueBound(HttpSessionBindingEvent event) | 该类的实例被放到Session域中时调用 |
| void valueUnbound(HttpSessionBindingEvent event) | 该类的实例从Session中移除时调用 |


2.2.3.2. HttpSessionActivationListener 监听器

HttpSessionActivationListener 监听器也叫钝化活化监听器

作用:HttpSessionActivationListener 监听 HttpSession 中对象的序列化和反序列化。在分布式系统中,它帮助处理对象的存储和恢复,允许在序列化和反序列化时执行特定操作。

HttpSessionActivationListener 的源码:

package javax.servlet.http;

import java.util.EventListener;

public interface HttpSessionActivationListener extends EventListener { 

    /**
     * Notification that the session is about to be passivated.
     *
     * @implSpec
     * The default implementation takes no action.
     * 
     * @param se the {@link HttpSessionEvent} indicating the passivation
     * of the session
     */
    default public void sessionWillPassivate(HttpSessionEvent se) {}

    /**
     * Notification that the session has just been activated.
     *
     * @implSpec
     * The default implementation takes no action.
     * 
     * @param se the {@link HttpSessionEvent} indicating the activation
     * of the session
     */
    default public void sessionDidActivate(HttpSessionEvent se) {}
} 

相关方法:

|-------------------------------------------|------------------------|
| 方法名 | 作用 |
| sessionWillPassivate(HttpSessionEvent se) | 该类实例和Session一起钝化到硬盘时调用 |
| sessionDidActivate(HttpSessionEvent se) | 该类实例和Session一起活化到内存时调用 |

相关推荐
zaim142 分钟前
计算机的错误计算(一百一十四)
java·c++·python·rust·go·c·多项式
limengshi13839244 分钟前
通信工程学习:什么是RIP路由信息协议
网络·网络协议·学习·智能路由器·信息与通信
xiaobuding_QAQ2 小时前
自用Proteus(8.15)常用元器件图示和功能介绍(持续更新...)
单片机·嵌入式硬件·学习·proteus
Starry_hello world2 小时前
二叉树实现
数据结构·笔记·有问必答
wei_shuo2 小时前
偏标记学习+图像分类(论文复现)
学习·分类·数据挖掘
hong_zc2 小时前
算法【Java】—— 二叉树的深搜
java·算法
进击的女IT3 小时前
SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
java·spring boot·后端
Мартин.3 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
Miqiuha3 小时前
lock_guard和unique_lock学习总结
java·数据库·学习
一 乐4 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习