JavaWeb之监听器

news2024/10/24 7:22:07

在JavaWeb开发中,常见的监听器(Listener)用于监听Web应用程序、会话(Session)、请求(Request)的生命周期或属性的变化。

应用域监听器:

应用域监听器(也称为ServletContextListener)用于监听Web应用程序的启动和关闭等生命周期事件。

1. ServletContextListener概述

ServletContextListener监听ServletContext对象的生命周期,ServletContext代表Web应用程序的全局域对象,通常是整个应用启动和关闭时触发监听事件。可以通过监听这些事件来在应用程序启动时执行初始化任务,或者在应用程序销毁时进行资源清理。

2. ServletContextListener接口中的方法

ServletContextListener接口主要有两个方法,分别对应Web应用的启动和关闭:

  • contextInitialized(ServletContextEvent sce): 在Web应用启动时执行。当服务器启动并加载Web应用时,该方法会被调用一次。通常在这里编写初始化应用的代码。

    常见用途

    • 加载应用配置文件。
    • 初始化资源(如数据库连接池、缓存、线程池等)。
    • 创建和设置全局共享的数据或对象
       @Override
          public void contextInitialized(ServletContextEvent sce) {
              ServletContext application = sce.getServletContext();
              System.out.println(application.hashCode() + "应用域初始化了");
          }
  • contextDestroyed(ServletContextEvent sce): 在Web应用关闭时执行。当服务器关闭Web应用或重新部署Web应用时,该方法会被调用一次。通常在这里编写清理资源的代码。

    常见用途

    • 关闭数据库连接。
    • 释放应用中使用的系统资源。
    • 停止后台线程或任务。
      @Override
          public void contextDestroyed(ServletContextEvent sce) {
              ServletContext application = sce.getServletContext();
              System.out.println(application.hashCode() + "应用域销毁了");
          }

 ServletContextEvent:简称sce 

是Java Web开发中与ServletContextListener监听器相关的一个事件类。它封装了ServletContext对象,用于在监听ServletContext(应用域对象)的生命周期变化时,传递相关信息。 

1. ServletContextEvent的定义

ServletContextEventjava.servlet包中的一个类,继承自java.util.EventObject,用于表示ServletContext对象发生的事件例如,应用程序启动或关闭时会生成一ServletContextEvent事件对象,并传递给ServletContextListener监听器。

2. ServletContextEvent的作用

当Web应用程序启动或关闭时,ServletContextListenercontextInitialized()contextDestroyed()方法会被调用,并且这些方法会接收到一个ServletContextEvent对象作为参数。通过这个对象,监听器可以获取到当前的ServletContext,从而操作应用范围的资源或数据。

3. ServletContextListener的典型用法 

示例:
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyAppListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // Web应用启动时执行
        System.out.println("应用已启动,执行初始化操作...");
        // 执行初始化操作,如加载配置文件、初始化数据库连接等
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Web应用关闭时执行
        System.out.println("应用已关闭,执行清理操作...");
        // 执行清理操作,如关闭数据库连接、释放资源等
    }
}

3.2. 配置监听器

监听器可以通过两种方式进行配置:

  • 方式1:在web.xml中配置监听器web.xml文件中配置监听器类:

<listener>
    <listener-class>com.example.MyAppListener</listener-class>
</listener>

方式2:使用注解@WebListener 在Java类上直接使用@WebListener注解,如上面示例中的MyAppListener

4. ServletContextListener的应用场景

4.1. 初始化全局资源

在应用启动时,开发者可以利用contextInitialized()方法初始化应用所需的全局资源。这些资源在整个应用生命周期中可能会被不同的组件或Servlet使用。例如:

  • 数据库连接池的初始化:在应用启动时创建数据库连接池,确保后续的请求可以直接使用。
  • 加载配置文件:可以加载应用程序的配置文件(如application.propertiesconfig.xml),并将其存储到ServletContext中,以便应用程序中的其他组件读取。
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 初始化数据库连接池
        DataSource dataSource = setupDataSource();
        sce.getServletContext().setAttribute("dataSource", dataSource);
    
        // 加载配置文件
        Properties appConfig = new Properties();
        try (InputStream input = sce.getServletContext().getResourceAsStream("/WEB-INF/appConfig.properties")) {
            appConfig.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sce.getServletContext().setAttribute("appConfig", appConfig);
    }
    

4.2. 释放资源

在应用关闭时,contextDestroyed()方法可以被用来释放全局资源或执行清理操作,例如:

  • 关闭数据库连接池:确保所有数据库连接都正确关闭,防止资源泄露。
  • 停止后台线程:如果应用在后台启动了定时任务或线程池,在关闭应用时应该停止这些任务,以释放系统资源。
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 获取数据库连接池
        DataSource dataSource = (DataSource) sce.getServletContext().getAttribute("dataSource");
        if (dataSource != null) {
            // 关闭连接池
            closeDataSource(dataSource);
        }
    
        // 停止后台任务
        ScheduledExecutorService scheduler = (ScheduledExecutorService) sce.getServletContext().getAttribute("scheduler");
        if (scheduler != null) {
            scheduler.shutdown();
        }
    }
    

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

方法名描述
attributeAdded当在ServletContext中添加属性时调用
attributeRemoved当从ServletContext中移除属性时调用
attributeReplaced当在ServletContext中的属性被替换或修改时调用

 此时要注意添加另一个接口ServletContextAttributeListener 

package com.listener;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebListener;

@WebListener
public class MyApplicationListener implements ServletContextListener , ServletContextAttributeListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext application = sce.getServletContext();
        System.out.println(application.hashCode() + "应用域初始化了");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext application = sce.getServletContext();
        System.out.println(application.hashCode() + "应用域销毁了");
    }

    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        ServletContext application = scae.getServletContext();

        // 增加的数据
        String key = scae.getName();
        Object value = scae.getValue();
        System.out.println(application.hashCode()+"应用域 增加了"+key +": "+value);
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        ServletContext application = scae.getServletContext();

        // 增加的数据
        String key = scae.getName();
        Object value = scae.getValue();
        System.out.println(application.hashCode()+"应用域 删除了"+key +": "+value);
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        ServletContext application = scae.getServletContext();

        // 增加的数据
        String key = scae.getName();
        Object value = scae.getValue();// 获取的是旧的值
        Object value2 = scae.getValue();// 获取的是新的值

        System.out.println(application.hashCode()+"应用域 修改了"+key +"的value值:  "+value+"    变成了" + value2);
    }
}
servlet1:
package com.servlet;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;

import java.io.IOException;
@WebServlet("/servlet1")
public class servlet1 extends HttpServlet {

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        // 向应用域中放入数据
        ServletContext servletContext = servletRequest.getServletContext();
        servletContext.setAttribute("keya","valuea");
    }

}
servlet2:
package com.servlet;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
@WebServlet("/servlet2")
public class servlet2 extends HttpServlet {
    // 向应用域改数据
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = req.getServletContext();
        servletContext.setAttribute("keya","valueXX");
    }
}
servlet3:
package com.servlet;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
@WebServlet("/servlet3")
public class servlet3 extends HttpServlet {
    // 删除应用域的数据
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = req.getServletContext();
        servletContext.removeAttribute("keya");
    }
}

在网页依次访问servlet1,servlet2,servlet3,得到控制台的显示:

session域和请求域的监听器其实都差不多,这里就以表格的形式来说明

HttpSessionBindingListener 监听当前监听器对象在 Session 域中的增加与移除:

HttpSessionBindingListener 方法一览

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2212930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年中国环境统计年鉴(EXCEL)

2023年中国环境统计年鉴(EXCEL) 1、时间&#xff1a;2023年 2、《Z国环境统计年鉴》是一本重要的年度参考资料&#xff0c;全面反映了Z国的环境状况与发展趋势。本年鉴收集整理了大量来自各级环境保护部门、科研机构以及相关领域的数据和统计信息&#xff0c;内容涵盖了大气、…

APB接口协议

APB 简介信号传输时序WriteWrite stobesReadError responseWrite transferRead transferMapping of PSLVERRProtection unit support 状态机 简介 APB&#xff08;Advanced Peripheral Bus&#xff09;是AMBA总线的一部分&#xff0c;从1998年第一版至今共有3个版本。 AMBA2 …

【专题】计算机网络概述

1. 计算机网络的作用及其发展史 1.1. 计算机网络的作用 二十一世纪的一些重要特征就是数字化、网络化和信息化&#xff0c;它是一个以网络为核心的信息时代。 网络现在已经成为信息社会的命脉和发展知识经济的重要基础。 信息时代以网络为核心。 (1) 网络 “网络”是一个统称…

UE4 材质学习笔记10(程序化噪波/覆雪树干着色器/岩层着色器)

一.程序化噪波 柏林噪波是一种能生成很好的随机图案的算法&#xff0c;它是一个无限的、不重复的图案&#xff0c;可以采用这种基础图案并以多种方式对其进行修改&#xff0c; 将它缩放并进行多次组合&#xff0c;就可以创建一个分形图案。这些组合的缩放等级称为一个Octave 这…

ArrayList和顺序表(下)

1. Java本身提供的ArrayList 在ArrayList和顺序表(上)那一节里面,我们自己实现了ArrayList的底层大部分代码,在这个基础上,我们就可以开始来了解Java本身提供的ArrayList. 1.1 ArrayList的三种构造方法 方法解释ArrayList()无参构造ArrayList(Collection<? extends E > …

‌ComfyUI 高级实战:实现华为手机的AI消除功能

大家好&#xff0c;我是每天分享AI应用的萤火君&#xff01; 不知道大家是否还记得华为 Pura 70的「AI消除」事件&#xff0c;当时使用 华为Pura 70 系列手机的智能消除功能时&#xff0c;该功能可以被用来消除照片中女性胸口处的衣物&#xff0c;这一功能曾引发广泛的关注和伦…

OpenAI Canvas最新发布,编程和写作迎来全新史诗级加强!

文章目录 零、前言一、GPT-40 with canvas操作指导写作领域加强建议编辑调整长度阅读水平添加最后的润色添加表情 编程领域加强选中代码问问题添加评论&#xff08;添加注释&#xff09;添加日志转换语言代码审查 二、感受 零、前言 最新消息&#xff0c;国庆期间OpenAI有大动…

使用管理员删除垃圾文件

1、先设置为管理员权限 2、执行删除文件命令 使用&#xff1a;del /f /s /q “文件夹位置”例如&#xff1a;del /f /s /q "C:\Program Files (x86)\my_code\.git"

2024深圳秋季糖酒会参会攻略!建议收藏

10月29日-31日&#xff0c;第111届全国糖酒商品交易会将在深圳国际会展中心&#xff08;宝安&#xff09;举办。本届糖酒会将邀请来自超四十个国家和地区的超4200家行业厂商和20万国内外专业观众到会交易交流&#xff0c;为食品酒类行业搭建一个集展示、交易、交流、合作于一体…

IP- guard产品版本升级指引详解

一、IP-guard服务器升级步骤 1、下载升级包(IPgUpgrade版本号.zip) 到IP-guard服务器 2、解压升级包,右键以管理员身份运行 (1)“升级包”解压 (2)右键以管理员身份运行“升级包” ࿰

报表工具如何助力企业报表开发?如何选择最适合的报表工具?一篇文章统统解答!

在当今瞬息万变的商业格局中&#xff0c;企业信息化建设已成为驱动业务飞跃与增强核心竞争力的核心引擎。然而&#xff0c;伴随业务数据的井喷式增长&#xff0c;企业在数据治理与价值挖掘方面遭遇了前所未有的挑战。数据孤岛、处理流程冗长、对业务动态调整反应迟缓&#xff0…

Leetcode 分割等和子集

这段代码的目的是解决 LeetCode 416 问题&#xff1a;分割等和子集&#xff0c;即判断一个只包含正整数的数组&#xff0c;是否能够将其分割成两个子集&#xff0c;使得这两个子集的元素和相等。 算法思想&#xff08;动态规划 - 背包问题&#xff09; 该问题本质上是一个经典…

Facebook减肥产品广告投放攻略

有不少刚开始投放facebook广告的小伙伴会感到疑惑&#xff0c;为什么别人的减肥产品跑的风生水起&#xff0c;销量羡煞旁人&#xff0c;自己的广告要不就是被拒要不就是没有流量&#xff0c;甚至还可能被封号&#xff0c;如果你也有这样的困扰&#xff0c;那一定要看完这篇文章…

组合式API有什么好处

什么是组合式API&#xff1f; 组合式 API (Composition API) 是一系列 API &#xff08;响应式API、生命周期钩子、依赖注入&#xff09;的集合。它不是函数式编程&#xff0c;组合式 API 是以 Vue 中数据可变的、细粒度的响应性系统为基础的&#xff0c;而函数式编程通常强调…

使用Python进行Web开发的15个框架指南

引言 在Python Web开发领域&#xff0c;有许多不同类型的框架可供选择&#xff0c;从轻量级到全功能型&#xff0c;再到专注于异步处理的框架。本文将介绍多个Python Web框架&#xff0c;帮助开发者根据具体需求选择合适的工具。 1.Flask&#xff1a;轻量级Web框架 Flask是一…

【C语言】深入理解指针(三)(下)

本篇文章将讲解以下知识&#xff1a; 1、二维数组传参的本质 2、函数指针变量 3、函数指针数组 1、二维数组传参的本质 有了数组指针的理解&#xff0c;我们就能弄清楚二维数组传参的本质了 例如&#xff1a; 在一维数组中&#xff0c;数组名是数字首元素的地址。但有两个例外…

【进阶OpenCV】 (10)--光流估计--->描绘运动物体轨迹

文章目录 光流估计一、基本原理二、计算步骤三、实现步骤1. 处理第一帧2. 寻找特征点3. 创建全零掩膜4. 流光估计函数介绍5. 主循环处理视频的每一帧5.1 流光估计5.2 绘制轨迹5.3 生成最终图像5.4 更新旧灰度图和旧特征点 6. 释放资源 总结 光流估计 光流估计是计算机视觉中的…

操作系统——磁盘管理

目录 前言基础实例1.1读取磁盘数据计算时间1.2磁盘调度算法1.3单双缓冲区1.4磁盘基础知识 前言 本文简述操作系统中有关磁盘的相关知识点&#xff0c;作为软件设计师考试资料复习 基础 磁盘管理是指对计算机中的磁盘进行有效地管理和使用的过程。磁盘管理包括以下方面&#…

软件测试工程师面试整理 —— 操作系统与网络基础!

在软件测试中&#xff0c;了解操作系统和网络基础知识对于有效地进行测试工作至关重要。无论是在配置测试环境、调试网络问题&#xff0c;还是在进行性能测试和安全测试时&#xff0c;这些知识都是不可或缺的。 1. 操作系统基础 操作系统&#xff08;Operating System, OS&am…

【Redis】网络模型(day10)

在本篇文章中&#xff0c;主要是对五种网络模型进行一个简单的介绍&#xff0c;然后对Redis4.0和6.0的网络模型进行一个概述。 用户空间和内核空间 在Linux系统上&#xff0c;分为用户空间、内核空间和硬件设备。硬件设备主要包括CPU、内存、网卡等物体&#xff0c;内核应用去…