🐲 一文搞懂 【】 Filter

一、观察者模式

二十三种设计模式之一:

  • 观察者:监控『被观察者』的行为,一旦发现『被观察者』触发了事件,就会调用事先准备好的方法执行操作。
  • 被观察者:『被观察者』一旦触发了被监控的事件,就会被『观察者』发现。

二、监听器

1、概念

监听器:专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。
Servlet监听器:Servlet规范中定义的一种特殊类,它用于监听Web应用程序中的ServletContext,HttpSession 和HttpServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。

2、分类

  • 域对象监听器
  • 域对象的属性域监听器
  • Session域中数据的监听器

3、监听器列表

①ServletContextListener

作用:监听ServletContext对象的创建与销毁

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

ServletContextEvent对象代表从ServletContext对象身上捕获到的事件,通过这个事件对象我们可以获取到ServletContext对象。

②HttpSessionListener

作用:监听HttpSession对象的创建与销毁

方法名 作用
sessionCreated(HttpSessionEvent hse) HttpSession对象创建时调用
sessionDestroyed(HttpSessionEvent hse) HttpSession对象销毁时调用

HttpSessionEvent对象代表从HttpSession对象身上捕获到的事件,通过这个事件对象我们可以获取到触发事件的HttpSession对象。

③ServletRequestListener

作用:监听ServletRequest对象的创建与销毁

方法名 作用
requestInitialized(ServletRequestEvent sre) ServletRequest对象创建时调用
requestDestroyed(ServletRequestEvent sre) ServletRequest对象销毁时调用

ServletRequestEvent对象代表从HttpServletRequest对象身上捕获到的事件,通过这个事件对象我们可以获取到触发事件的HttpServletRequest对象。另外还有一个方法可以获取到当前Web应用的ServletContext对象。

④ServletContextAttributeListener

作用:监听ServletContext中属性的创建、修改和销毁

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

ServletContextAttributeEvent对象代表属性变化事件,它包含的方法如下:

方法名 作用
getName() 获取修改或添加的属性名
getValue() 获取被修改或添加的属性值
getServletContext() 获取ServletContext对象

⑤HttpSessionAttributeListener

作用:监听HttpSession中属性的创建、修改和销毁

方法名 作用
attributeAdded(HttpSessionBindingEvent se) 向HttpSession中添加属性时调用
attributeRemoved(HttpSessionBindingEvent se) 从HttpSession中移除属性时调用
attributeReplaced(HttpSessionBindingEvent se) 当HttpSession中的属性被修改时调用

HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:

方法名 作用
getName() 获取修改或添加的属性名
getValue() 获取被修改或添加的属性值
getSession() 获取触发事件的HttpSession对象

⑥ServletRequestAttributeListener

作用:监听ServletRequest中属性的创建、修改和销毁

方法名 作用
attributeAdded(ServletRequestAttributeEvent srae) 向ServletRequest中添加属性时调用
attributeRemoved(ServletRequestAttributeEvent srae) 从ServletRequest中移除属性时调用
attributeReplaced(ServletRequestAttributeEvent srae) 当ServletRequest中的属性被修改时调用

ServletRequestAttributeEvent对象代表属性变化事件,它包含的方法如下:

方法名 作用
getName() 获取修改或添加的属性名
getValue() 获取被修改或添加的属性值
getServletRequest () 获取触发事件的ServletRequest对象

⑦HttpSessionBindingListener

作用:监听某个对象在Session域中的创建与移除

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

HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:

方法名 作用
getName() 获取当前事件涉及的属性名
getValue() 获取当前事件涉及的属性值
getSession() 获取触发事件的HttpSession对象

⑧HttpSessionActivationListener

作用:监听某个对象在Session中的序列化与反序列化。

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

HttpSessionEvent对象代表事件对象,通过getSession()方法获取事件涉及的HttpSession对象。

三、案例

1、提出需求

目前JDBCUtils中创建数据源对象是在第一次访问数据库时:

JDBCUtils这个类初始化时需要执行静态代码块:

  • 读取jdbc.properties文件(I/O操作)
  • 创建DataSource对象(大对象)

上面提到的两个操作都比较耗时,最好能改成Web应用启动时执行

2、创建监听器

①创建监听器类

java 复制代码
package com.demo.listener;  
  
import jakarta.servlet.ServletContextEvent;  
import jakarta.servlet.ServletContextListener;  
  
public class ListenerDataSourceInit implements ServletContextListener {  
  
    @Override  
    public void contextInitialized(ServletContextEvent sce) {  
        try {  
            // 通过反射加载类,由于类中有静态代码块,所以加载类就能够执行静态代码块  
            Class.forName("com.atguigu.demo.utils.JDBCUtils");  
        } catch (ClassNotFoundException e) {  
            throw new RuntimeException(e);  
        }  
    }  
}

②注册监听器类

xml 复制代码
<listener>  
    <!-- 注册监听器:专门负责在 Web 应用启动时初始化数据源 -->  
    <listener-class>com.demo.listener.ListenerDataSourceInit</listener-class>  
</listener>

3、提出进一步的问题

  • jdbc.properties文件路径写在Java代码中,如果有修改,需要经过编译、重新部署才能生效
  • 如果把jdbc.properties文件路径在web.xml中配置,那么web.xml是文本文件,可以在服务器端直接修改,不必经过编译这个环节

①配置Web应用初始化参数

xml 复制代码
<!-- 设定 Web 应用初始化参数 -->  
<context-param>  
    <!-- 初始化参数名称 -->  
    <param-name>jdbcConfigLocation</param-name>  
  
    <!-- 初始化参数值 -->  
    <param-value>jdbc.properties</param-value>  
</context-param>

②重构JDBCUtils代码

java 复制代码
// 数据源对象声明为成员变量  private static DataSource dataSource;  
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();  
  
private static String jdbcConfigLocation;  
  
public static void setJdbcConfigLocation(String jdbcConfigLocation) {  
    JDBCUtils.jdbcConfigLocation = jdbcConfigLocation;  
}  
  
public static void initDataSource() {  
    try {  
        // 1、创建 Properties 对象  
        Properties properties = new Properties();  
  
        // 2、加载外部属性文件  
        InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream(jdbcConfigLocation);  
  
        // 3、加载外部属性文件  
        properties.load(inputStream);  
  
        // 4、给数据源成员变量赋值  
        dataSource = DruidDataSourceFactory.createDataSource(properties);  
    } catch (Exception e) {  
        throw new RuntimeException(e);  
    }  
}

③重构监听器代码

java 复制代码
package com.demo.listener;  
  
import com.atguigu.demo.utils.JDBCUtils;  
import jakarta.servlet.ServletContext;  
import jakarta.servlet.ServletContextEvent;  
import jakarta.servlet.ServletContextListener;  
  
public class ListenerDataSourceInit implements ServletContextListener {  
  
    @Override  
    public void contextInitialized(ServletContextEvent sce) {  
        // 获取 ServletContext 对象  
        ServletContext servletContext = sce.getServletContext();  
  
        // 借助 ServletContext 对象读取 Web 应用初始化参数  
        String jdbcConfigLocation = servletContext.getInitParameter("jdbcConfigLocation");  
  
        // 对 JDBCUtils 中的成员变量进行赋值  
        JDBCUtils.setJdbcConfigLocation(jdbcConfigLocation);  
  
        // 调用专门的方法初始化数据源  
        JDBCUtils.initDataSource();  
  
        // 通过反射加载类,由于类中有静态代码块,所以加载类就能够执行静态代码块  
        // Class.forName("com.atguigu.demo.utils.JDBCUtils");  
    }  
}

4、ContextLoaderListener

这是我们在Spring、SpringMVC、Mybatis三大框架整合时需要使用的一个监听器。

使用这个监听器需要我们在web.xml配置它。

然后为了配合ContextLoaderListener,需要在context-param中指定Spring配置文件的位置。

所以我们设定上面JDBCUtils这个场景,是为了把监听器和context-param用一下,将来到框架里面用到的时候,有个印象。

四、Web后端内容总结

相关推荐
欧恩意3 小时前
【Tools】Java反汇编工具推荐
java·汇编
苍何3 小时前
字节发力,豆包大模型2.0 震撼来袭(附 Trae 实测)
后端
苍何3 小时前
不会剪辑的人,开始用 AI 批量出爆款了
后端
苍何3 小时前
百度 APP 正式接入 OpenClaw,所有人限时免费!
后端
寻星探路3 小时前
【JVM 终极通关指南】万字长文从底层到实战全维度深度拆解 Java 虚拟机
java·开发语言·jvm·人工智能·python·算法·ai
lbb 小魔仙3 小时前
【Java】Java 实战项目:手把手教你写一个电商订单系统
android·java·python
星河耀银海3 小时前
Java安全开发实战:从代码防护到架构安全
java·安全·架构
青云交3 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市水资源管理与节水策略制定中的应用
java·java 大数据·java 大数据可视化·城市水资源管理·spark 数据清洗·echarts 热力图·管网漏损控制
紫陌涵光4 小时前
112. 路径总和
java·前端·算法
workflower4 小时前
多变量时间序列预测
java·hadoop·nosql·需求分析·big data·结对编程