Filter 过滤器 与Listener 监听器

一、过滤器 Filter

Filter 是 JavaWeb 三大组件之一,核心作用是拦截请求,而非处理请求,与 Servlet 配合实现请求的预处理、权限校验等功能。

1. 过滤器核心概念

  1. 用户请求目标 Servlet 时,会先执行绑定该请求的 Filter,Filter 决定是否 "放行",放行则执行目标 Servlet,不放行则终止请求。
  2. 执行完 Servlet 的代码后,会回溯执行 Filter 中放行代码后的逻辑,请求并非给客户端输出后就结束。
  3. 一个目标资源可绑定多个 Filter,执行遵循 "先进先执行、后进先回溯" 规则,即多个过滤器执行顺序为 1 前→2 前→目标资源→2 后→1 后。

2. 过滤器创建与配置

  1. 创建步骤:定义 Java 类实现javax.servlet.Filter接口,并重写init()doFilter()destroy()三个核心方法。
  2. 配置方式:在 web.xml 中通过<filter><filter-mapping>标签配置,也可使用注解(与 Servlet 注解方式类似)。
  3. 路径匹配规则:与 Servlet 的url-pattern完全一致,分为完全路径匹配(/aaa)、目录匹配(/aaa/、/)、扩展名匹配(*.do)三种。

3. 过滤器生命周期

  1. init(FilterConfig):服务器启动时创建 Filter 实例,每个类型的 Filter 仅创建一个,创建后立即调用该方法完成初始化,仅执行一次。
  2. doFilter(ServletRequest, ServletResponse, FilterChain):用户每次访问目标资源时执行,是过滤器的核心方法;需调用FilterChain.doFilter()方法才会放行,否则目标资源无法执行。
  3. destroy():Filter 实例创建后存入服务器缓存持续使用,服务器关闭时销毁实例,销毁前调用该方法,仅执行一次。

4. FilterConfig

  1. 与 ServletConfig 功能相似,对应 web.xml 中 Filter 的配置信息,是init()方法的参数,无法自行创建。
  2. 核心方法:
    • ServletContext getServletContext():获取当前 Web 应用的 ServletContext 对象。
    • String getFilterName():获取<filter-name>配置的过滤器名称。
    • String getInitParameter(String name):根据参数名获取 Filter 的初始化参数值。
    • Enumeration getInitParameterNames():获取 Filter 所有初始化参数的名称,可遍历获取所有参数。
  3. 配置方式:在 web.xml 的<filter>标签中添加<init-param>子元素,包含<param-name><param-value>,可配置多个。

5. FilterChain 过滤器链

  1. doFilter()方法的参数,仅包含doFilter(ServletRequest, ServletResponse)一个方法,核心作用是实现放行逻辑。
  2. 放行的本质:调用该方法并非直接执行目标资源,而是执行下一个过滤器doFilter()方法;若当前过滤器是最后一个,则执行目标资源。
  3. 代码执行规则:FilterChain.doFilter()方法之前 的代码,在目标资源执行前执行;之后的代码,在目标资源执行后执行。

6. 过滤器执行顺序

  1. 单个目标资源绑定多个过滤器时,执行顺序由web.xml 中的部署顺序决定。
  2. 部署规则:<filter><filter-mapping>标签的书写顺序即为过滤器的执行顺序,先配置的过滤器先执行,后配置的后执行。
  3. 回溯规则:目标资源执行完成后,过滤器按执行顺序的倒序执行放行后的代码,即最后执行的过滤器先回溯。

7. 过滤器目标资源设置

  1. 通过url-pattern匹配:如/*拦截所有请求,/admin/*拦截管理员路径下的所有敏感资源,与 Servlet 路径配置一致。
  2. 通过 Servlet 名称匹配:在<filter-mapping>中使用<servlet-name>标签,指定拦截某个具体的 Servlet,当访问该 Servlet 时触发过滤器。

8. 过滤器核心应用场景

  1. 预处理请求:如设置请求和响应的编码格式,解决中文乱码问题,此类场景一般都会放行,仅做前置准备工作。
  2. 权限校验:如判断用户是否登录、用户 IP 是否被禁用、是否拥有访问资源的权限,不满足条件则拒绝放行。
  3. 后置处理:在目标资源执行后,对响应的数据进行加工处理,如统一处理返回结果、添加响应头信息。

9. 过滤器经典应用:解决 POST 中文乱码

  1. 配置:在 web.xml 中配置过滤器,设置初始化参数encode为 UTF-8,url-pattern/*拦截所有请求。
  2. 核心代码:在doFilter()方法中,通过request.setCharacterEncoding(encode)设置请求编码,通过response.setCharacterEncoding(encode)response.setContentType("text/html;charSet="+encode)设置响应编码,最后调用放行方法。
  3. 优势:一次配置,全局生效,无需在每个 Servlet 中单独设置编码,简化开发。

二、监听器 Listener

Listener 是 JavaWeb 三大组件之一,基于观察者模式实现,核心作用是监听 Web 应用中域对象的状态变化,当事件触发时自动执行对应的处理方法。

1. 监听器核心概述

  1. 监听的事件源:JavaWeb 中的三大域对象,即ServletContext(应用域)、HttpSession(会话域)、ServletRequest(请求域)。
  2. 监听的事件类型:域对象的创建与销毁 、域对象中属性的添加 / 修改 / 删除HttpSession的特殊状态变化(如钝化、活化)。
  3. 核心作用:感知域对象的状态变化,在事件触发时执行自定义逻辑,如统计在线人数、初始化应用全局数据、监听用户会话状态。

2. 常用核心监听器

(1)ServletContextListener:监听 ServletContext 对象
  1. 监听应用的启动与关闭,ServletContext在服务器启动时创建,服务器关闭时销毁。
  2. 核心方法:
    • contextInitialized(ServletContextEvent evt):ServletContext 对象创建后调用,可用于初始化应用全局数据(如加载配置文件、初始化全局变量)。
    • contextDestroyed(ServletContextEvent evt):ServletContext 对象销毁前调用,可用于释放应用资源(如关闭数据库连接)。
(2)HttpSessionListener:监听 HttpSession 对象
  1. 监听用户会话的创建与销毁,HttpSession在用户第一次访问应用时创建,会话超时 / 手动销毁时销毁。
  2. 核心方法:
    • sessionCreated(HttpSessionEvent evt):HttpSession 对象创建后调用,可用于统计在线人数、记录用户登录信息。
    • sessionDestroyed(HttpSessionEvent evt):HttpSession 对象销毁前调用,可用于统计用户下线、清理会话数据。
(3)ServletRequestListener:监听 ServletRequest 对象
  1. 监听请求的创建与销毁,ServletRequest在用户每次发起请求时创建,请求响应完成后销毁。
  2. 核心方法:
    • requestInitialized(ServletRequestEvent sre):ServletRequest 对象创建后调用,可用于记录请求日志、获取请求信息。
    • requestDestroyed(ServletRequestEvent sre):ServletRequest 对象销毁前调用,可用于清理请求相关资源。

3. 监听器的使用步骤

  1. 定义实现类:创建 Java 类,实现对应的监听器接口(可同时实现多个监听器接口,如同时实现 ServletContextListener 和 HttpSessionListener)。
  2. 重写方法:根据实现的接口,重写对应的事件处理方法,编写自定义业务逻辑。
  3. 配置注册:在 web.xml 中通过<listener>标签配置,指定监听器的全类名,服务器启动时会自动加载并注册。

4. 监听器经典应用:实现在线人数实时统计

  1. 核心思路:通过HttpSessionListener监听会话的创建与销毁,会话创建则在线人数 + 1,会话销毁则在线人数 - 1;通过ServletContextListener初始化在线人数为 0,并将人数存入ServletContext(全局共享)。
  2. 核心步骤:
    • 监听器实现ServletContextListenerHttpSessionListener接口,定义在线人数变量,默认值为 0。
    • contextInitialized方法:将在线人数初始值存入 ServletContext,实现全局共享。
    • sessionCreated方法:从 ServletContext 获取当前人数,自增后重新存入,实现人数 + 1。
    • sessionDestroyed方法:从 ServletContext 获取当前人数,自减后重新存入,实现人数 - 1。
  3. 页面展示:在 JSP 页面中通过 EL 表达式${count}获取 ServletContext 中的在线人数,实现实时展示。
  4. 会话销毁:通过request.getSession().invalidate()手动销毁会话,模拟用户退出,触发人数 - 1。
相关推荐
Leo.yuan4 小时前
实时ETL怎么做?有哪些好用的ETL工具?
数据仓库·etl
晨晖25 小时前
Servlet的快速入门,请求和响应
hive·hadoop·servlet
AllData公司负责人5 小时前
AllData数据中台通过集成DolphinScheduler+Seatunnel实现SAP HANA数据库同步到Doris数据仓库
数据库·数据仓库·sap hana
yumgpkpm6 小时前
AI算力纳管工具GPUStack Server+华为鲲鹏+麒麟操作系统 保姆级安装过程
人工智能·hadoop·华为
`林中水滴`6 小时前
【数据仓库】Iceberg、Hudi、Delta Lake、Paimon:四大开源湖表格式怎么选?
数据仓库
黄昏回响6 小时前
计算机系统基础知识(补充篇):数据库——数据仓库、数据中台与大数据技术详解
大数据·数据库·数据仓库
hellolianhua6 小时前
测试集群hdfs和mapreduce
大数据·hadoop·hdfs
淡定一生233321 小时前
数据仓库中的退化维度
数据仓库
smchaopiao1 天前
Hive中的排序与分桶技术详解
数据仓库·hive·hadoop