前端视角 Java Web 入门手册 4.4:Web 开发基础—— Listener

在 Java Servlet 规范中,Listener 是一种特殊的 Servlet 组件,用于监听和处理 Web 应用中的各种事件。这些事件可能涉及应用的生命周期、会话的创建与销毁、请求的开始与结束等。通过 Listener,开发者可以在特定事件发生时自动执行相应的逻辑,无需在业务代码中显式调用。

Java Servlet API 提供了多种 Listener 接口,允许开发者根据需要选择合适类型来监听特定事件

  • ServletContextListener:监听整个 Web 应用的初始化和销毁事件
  • HttpSessionListener:监听 Session 会话的创建和销毁事件
  • ServletRequestListener:监听请求对象 Request 的创建和销毁事件
  • ServletContextAttributeListener:监听 ServletContext 对象属性的改变事件
  • HttpSessionAttributeListener:监听 HttpSession 对象属性的改变事件
  • ServletRequestAttributeListener:监听 ServletRequest 对象属性的改变事件

Listener 的工作原理

Listener 工作的核心在于 Servlet 容器对特定事件的监听和触发机制。当这些事件发生时,容器自动调用相应的 Listener 方法,以执行预定义的逻辑。整个过程无需开发者手动触发 Listener

  1. 事件触发:当特定的事件发生时,如应用启动、会话创建等,Servlet 容器会检测并触发相应的事件
  2. Listener 响应:已注册的 Listener 会响应该事件,执行其定义的逻辑
  3. 生命周期管理:Servlet 容器负责管理 Listener 的生命周期,包括实例化、调用方法和销毁
plain 复制代码
事件发生(如应用启动) 
         │
         ▼
Servlet 容器检测事件
         │
         ▼
调用相应 Listener 的方法
         │
         ▼
Listener 执行逻辑(如初始化资源)

创建和配置 Listener

和 Filter 的使用非常类似,使用 Listener,需要完成以下步骤:

  1. 穿件类实现相应的 Listener 接口
  2. 通过 @WebListener 注解或在 web.xml 文件中配置 Listener

实现 Listener 接口

创建一个 Java 类并实现所需的 Listener 接口。通常需要覆盖接口中的所有方法,以响应特定事件

java 复制代码
package org.example;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener // 使用注解注册 Listener
public class AppContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // Web 应用启动时执行
        System.out.println("Web 应用启动,初始化全局资源。");
        // 例如,读取配置文件、初始化数据库连接池等
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Web 应用关闭时执行
        System.out.println("Web 应用关闭,释放全局资源。");
        // 例如,关闭数据库连接池、销毁缓存等
    }
}

使用 web.xml 配置 Listener

尽管注解提供了便捷的配置方式,但在复杂场景下通过 web.xml 文件配置 Listener 会更清晰,在 web.xml 中,Listener 的加载顺序由 <listener> 标签的声明顺序决定

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">

    <!-- 注册 ServletContextListener -->
    <listener>
        <listener-class>org.example.AppContextListener</listener-class>
    </listener>

    <!-- 其 它配置 -->
    
</web-app>

ServletContextListener

ServletContext 表示整个 Web 应用程序的上下文环境,ServletContextListener 可以监听 ServletContext 对象的创建和销毁事件,实现对整个 Web 应用程序的初始化和清理等操作,典型用途:

  • 初始化全局资源,如数据库连接池、配置文件读取等
  • 释放全局资源,确保资源正确关闭,避免内存泄漏

接口提供了两个方法:

  • contextInitialized:ServletContext 被初始化时容器调用,可以在此方法中进行 Web 应用程序的初始化操作,例如创建和配置数据库连接池、加载配置文件等
  • contextDestroyed:ServletContext 被销毁时容器调用,可以在此方法中进行 Web 应用程序的清理操作,例如关闭数据库连接池、释放系统资源等
java 复制代码
public class MyServletContextListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        ServletContext context = event.getServletContext();
        // 在 ServletContext 中设置全局变量
        context.setAttribute("dbURL", "jdbc:mysql://localhost/demo");
        context.setAttribute("dbUser", "test");
        context.setAttribute("dbPassword", "123456");
    }

    public void contextDestroyed(ServletContextEvent event) {
        ServletContext context = event.getServletContext();
        // 关闭数据库连接池等资源
        // ...
    }
}

使用 @WebListener 注解可以注册 Listener,同样也可以在 web.xml 中配置

xml 复制代码
<listener>
  <listener-class>com.example.MyServletContextListener</listener-class>
</listener>

这样容器在启动 Web 应用程序时会创建 MyServletContextListener 的实例,并在 ServletContext 初始化和销毁时分别调用 contextInitialized() 和 contextDestroyed() 方法

HttpSessionListener

HttpSession 对象表示用户会话,用于跟踪用户在应用程序中的活动。HttpSessionListener 可以监听 HttpSession 对象的创建和销毁事件,实现对用户会话的跟踪和管理等操作,典型用途:

  • 跟踪活跃会话数,监控用户活动。
  • 在会话创建时初始化会话属性。
  • 在会话销毁时清理资源或记录日志。

接口提供了两个方法

  • sessionCreated:HttpSession 对象被创建时容器调用,可以在此方法中记录用户访问信息、设置 session 的超时时间等
  • sessionDestroyed:HttpSession 对象被销毁时容器调用,可以在此方法中清理用户信息、释放资源等
java 复制代码
public class MySessionListener implements HttpSessionListener {
    
    public void sessionCreated(HttpSessionEvent event) {
        HttpSession session = event.getSession();
        // 记录用户访问信息
        String sessionId = session.getId();
        String ipAddress = session.getAttribute("userIPAddress");
        System.out.println("Session created: " + sessionId + ", IP address: " + ipAddress);
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        HttpSession session = event.getSession();
        // 清理用户信息
        session.removeAttribute("userInfo");
        // ...
    }
}

ServletRequestListener

ServletRequest 对象表示客户端请求,封装了客户端请求的相关信息。ServletRequestListener 可以监听 ServletRequest 对象的创建和销毁事件,实现对请求参数的封装、请求时间的记录等操作,接口提供了两个方法

  • requestInitialized:ServletRequest 对象被创建时容器调用,可以在此方法中记录请求时间、封装请求参数等
  • requestDestroyed:ServletRequest 对象被销毁时容器调用,可以在此方法中释放资源、记录请求处理结果等
java 复制代码
public class MyRequestListener implements ServletRequestListener {

    public void requestInitialized(ServletRequestEvent event) {
        ServletRequest request = event.getServletRequest();
        // 记录请求时间
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
    }

    public void requestDestroyed(ServletRequestEvent event) {
        ServletRequest request = event.getServletRequest();
        // 计算请求处理时间
        long startTime = (long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        long processingTime = endTime - startTime;
        request.removeAttribute("startTime");
        // 记录请求处理结果
        System.out.println("Request processed in " + processingTime + " ms");
    }
}

修改属性相关

除了常见的 ServletContextListener、HttpSessionListener、ServletRequestListener 外,还有一些 Listener 用于监听 ServletContextAttribute、HttpSessionAttribute、ServletRequestAttribute 等对象的属性修改事件

  • ServletContextAttributeListener:用于监听 ServletContextAttribute 的添加、删除和替换事件。在 ServletContextAttribute 被添加、删除或替换时,会触发 attributeAdded()、attributeRemoved() 或 attributeReplaced() 方法
  • HttpSessionAttributeListener:用于监听 HttpSessionAttribute 的添加、删除和替换事件。在 HttpSessionAttribute 被添加、删除或替换时,会触发 attributeAdded()、attributeRemoved() 或 attributeReplaced() 方法
  • ServletRequestAttributeListener:用于监听 ServletRequestAttribute 的添加、删除和替换事件。在 ServletRequestAttribute 被添加、删除或替换时,会触发 attributeAdded()、attributeRemoved() 或 attributeReplaced() 方法
java 复制代码
public class MyServletContextAttributeListener implements ServletContextAttributeListener {

    public void attributeAdded(ServletContextAttributeEvent event) {
        String attributeName = event.getName();
        Object attributeValue = event.getValue();
        System.out.println("Attribute added: " + attributeName + "=" + attributeValue);
    }

    public void attributeRemoved(ServletContextAttributeEvent event) {
        String attributeName = event.getName();
        Object attributeValue = event.getValue();
        System.out.println("Attribute removed: " + attributeName + "=" + attributeValue);
    }

    public void attributeReplaced(ServletContextAttributeEvent event) {
        String attributeName = event.getName();
        Object oldAttributeValue = event.getValue();
        Object newAttributeValue = event.getServletContext().getAttribute(attributeName);
        System.out.println("Attribute replaced: " + attributeName + "=" + oldAttributeValue + "->" + newAttributeValue);
    }
}
相关推荐
计算机-秋大田1 分钟前
基于Spring Boot的宠物健康顾问系统的设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
JouJz8 分钟前
Java虚拟机之垃圾收集(一)
java·开发语言·jvm
uhakadotcom13 分钟前
OpenHands:AI 驱动的软件开发框架
后端·面试·github
源码姑娘20 分钟前
基于DeepSeek的智慧医药系统(源码+部署教程)
java·人工智能·程序人生·毕业设计·springboot·健康医疗·课程设计
morris13126 分钟前
【redis】布隆过滤器的Java实现
java·redis·布隆过滤器
uhakadotcom26 分钟前
FinGPT:金融领域的开源语言模型框架
后端·面试·github
五行星辰39 分钟前
Java链接redis
java·开发语言·redis
编程毕设39 分钟前
【含文档+PPT+源码】基于微信小程序的在线考试与选课教学辅助系统
java·微信小程序·小程序
异常驯兽师42 分钟前
Java集合框架深度解析:List、Set与Map的核心区别与应用指南
java·开发语言·list
计算机学姐1 小时前
基于Asp.net的教学管理系统
vue.js·windows·后端·sqlserver·c#·asp.net·visual studio