🐲 一文搞懂 【】 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后端内容总结

相关推荐
java程序员CC几秒前
使用springboot+easyexcel实现导出excel并合并指定单元格
spring boot·后端·excel
风象南8 分钟前
SpringBoot中内置的49个常用工具类
java·spring boot·后端
lybugproducer2 小时前
创建型设计模式之:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式
java·设计模式·建造者模式·简单工厂模式·工厂方法模式·抽象工厂模式·面向对象
南客先生2 小时前
马架构的Netty、MQTT、CoAP面试之旅
java·mqtt·面试·netty·coap
Minyy112 小时前
SpringBoot程序的创建以及特点,配置文件,LogBack记录日志,配置过滤器、拦截器、全局异常
xml·java·spring boot·后端·spring·mybatis·logback
百锦再2 小时前
Java与Kotlin在Android开发中的全面对比分析
android·java·google·kotlin·app·效率·趋势
武昌库里写JAVA3 小时前
39.剖析无处不在的数据结构
java·vue.js·spring boot·课程设计·宠物管理
画个大饼4 小时前
Go语言实战:快速搭建完整的用户认证系统
开发语言·后端·golang
Nelson_hehe6 小时前
Java基础第四章、面向对象
java·语法基础·面向对象程序设计
Thomas_YXQ6 小时前
Unity3D Lua集成技术指南
java·开发语言·驱动开发·junit·全文检索·lua·unity3d