当前位置: 首页 > news >正文

JavaWeb学习——过滤器和监听器

过滤器(Filter)

过滤器是 JavaWeb 中的一种重要组件,用于在请求到达目标资源(如 Servlet、JSP)之前或响应返回客户端之前,对请求和响应进行预处理或后处理。过滤器通常用于实现一些通用的功能,如日志记录、权限验证、字符编码设置等。过滤器通常用于以下场景:

  • 日志记录:记录请求的详细信息。
  • 权限验证:检查用户是否有权限访问某些资源。
  • 字符编码设置:统一设置请求和响应的字符编码。
  • 数据压缩:对响应数据进行压缩。
  • 敏感词过滤:对请求参数或响应内容进行过滤。

过滤器的工作原理

过滤器是基于责任链模式(Chain of Responsibility)实现的。多个过滤器可以形成一个链,请求和响应会依次经过这些过滤器,最后到达目标资源。

过滤器的工作流程

  1. 客户端发送请求到服务器。
  2. 请求首先经过过滤器链中的第一个过滤器。
  3. 过滤器对请求进行处理,然后调用 chain.doFilter() 将请求传递给下一个过滤器。
  4. 请求最终到达目标资源(如 Servlet 或 JSP)。
  5. 目标资源生成响应后,响应会依次经过过滤器链中的过滤器。
  6. 响应最终返回客户端。

在这里插入图片描述

过滤器的生命周期

过滤器的生命周期由 Web 容器(如 Tomcat)管理,分为以下三个阶段:

  1. 初始化(init)
    • 过滤器在 Web 应用启动时初始化。
    • 可以通过 init() 方法加载配置或资源。
  2. 过滤(doFilter)
    • 每次请求和响应都会调用 doFilter() 方法。
    • 这是过滤器的核心方法,用于处理请求和响应。
  3. 销毁(destroy)
    • 过滤器在 Web 应用关闭时销毁。
    • 可以通过 destroy() 方法释放资源。

过滤器的使用步骤

  1. 实现 Filter 接口

创建一个类并实现 javax.servlet.Filter 接口,重写 init()doFilter()destroy() 方法。

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*") // 过滤所有请求
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
        System.out.println("Filter initialized");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 对请求进行预处理
        System.out.println("Before request processing");
        request.setCharacterEncoding("UTF-8"); // 设置请求编码
        response.setCharacterEncoding("UTF-8"); // 设置响应编码

        // 将请求传递给下一个过滤器或目标资源
        chain.doFilter(request, response);

        // 对响应进行后处理
        System.out.println("After response processing");
    }

    @Override
    public void destroy() {
        // 销毁操作
        System.out.println("Filter destroyed");
    }
}
  1. 配置过滤器

可以通过以下两种方式配置过滤器:

  1. 注解配置:使用 @WebFilter 注解(如上面的示例)。
  2. XML 配置:在 web.xml 中配置过滤器。
<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern> <!-- 过滤所有请求 -->
</filter-mapping>

过滤器的常见应用场景

  1. 字符编码设置

    • 统一设置请求和响应的字符编码,避免乱码问题。
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    
  2. 权限验证

    • 检查用户是否登录,如果没有登录则重定向到登录页面。
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpSession session = httpRequest.getSession();
    if (session.getAttribute("user") == null) {
        ((HttpServletResponse) response).sendRedirect("login.jsp");
        return;
    }
    chain.doFilter(request, response);
    
  3. 日志记录

    • 记录请求的 URL、IP 地址等信息。
    System.out.println("Request URL: " + httpRequest.getRequestURL());
    System.out.println("Client IP: " + httpRequest.getRemoteAddr());
    
  4. 敏感词过滤

    • 对请求参数或响应内容进行敏感词替换。
    String content = request.getParameter("content");
    if (content != null) {
        content = content.replace("敏感词", "***");
        request.setAttribute("content", content);
    }
    chain.doFilter(request, response);
    

过滤器的注意事项

  • 过滤器链的顺序
    • 如果有多个过滤器,它们的执行顺序由配置顺序决定(XML 配置)或过滤器名称的字母顺序决定(注解配置)。
  • 性能影响
    • 过滤器会增加请求处理的时间,因此应避免在过滤器中执行耗时操作。
  • 线程安全性
    • 过滤器是单例的,多个请求会共享同一个过滤器实例,因此需要注意线程安全问题。

过滤器的优点

  • 解耦:将通用功能(如日志记录、权限验证)从业务逻辑中分离出来,提高代码的可维护性。
  • 可插拔:过滤器可以动态添加或移除,不影响现有代码。
  • 灵活性:可以通过配置控制过滤器的执行顺序和作用范围。

过滤器链的使用

过滤器链是 JavaWeb 中多个过滤器按照一定顺序组成的链式结构。当一个请求到达时,它会依次经过过滤器链中的每一个过滤器,最后到达目标资源(如 Servlet 或 JSP)。过滤器链的使用可以让我们将不同的功能模块(如日志记录、权限验证、字符编码设置等)拆分成多个过滤器,从而提高代码的可维护性和复用性。

在这里插入图片描述

过滤器链的配置

过滤器链的执行顺序由过滤器的配置顺序决定。可以通过以下两种方式配置过滤器链:

  1. 注解配置

使用 @WebFilter 注解配置过滤器时,过滤器的执行顺序由过滤器类名的字母顺序决定。

@WebFilter("/*")
public class FilterA implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("FilterA: Before request");
        chain.doFilter(request, response);
        System.out.println("FilterA: After response");
    }
}

@WebFilter("/*")
public class FilterB implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("FilterB: Before request");
        chain.doFilter(request, response);
        System.out.println("FilterB: After response");
    }
}

在上面的示例中,FilterA 会先于 FilterB 执行,因为 FilterA 的类名字母顺序靠前。

  1. XML 配置

web.xml 中配置过滤器时,过滤器的执行顺序由 <filter-mapping> 的配置顺序决定。

<filter>
    <filter-name>FilterA</filter-name>
    <filter-class>com.example.FilterA</filter-class>
</filter>
<filter-mapping>
    <filter-name>FilterA</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>FilterB</filter-name>
    <filter-class>com.example.FilterB</filter-class>
</filter>
<filter-mapping>
    <filter-name>FilterB</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在上面的示例中,FilterA 会先于 FilterB 执行,因为 FilterA<filter-mapping> 配置在前。

过滤器链的使用示例

以下是一个完整的示例,展示了如何使用过滤器链实现日志记录、权限验证和字符编码设置。

FilterA:日志记录

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class FilterA implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("FilterA: Logging request");
        chain.doFilter(request, response);
        System.out.println("FilterA: Logging response");
    }
}

FilterB:权限验证

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebFilter("/*")
public class FilterB implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpSession session = httpRequest.getSession();
        if (session.getAttribute("user") == null && !httpRequest.getRequestURI().endsWith("login.jsp")) {
            ((HttpServletResponse) response).sendRedirect("login.jsp");
            return;
        }
        System.out.println("FilterB: Permission check passed");
        chain.doFilter(request, response);
    }
}

FilterC:字符编码设置

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class FilterC implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        System.out.println("FilterC: Character encoding set");
        chain.doFilter(request, response);
    }
}

以上三个过滤器按照 FilterAFilterBFilterC 的顺序执行,那么它们的执行流程如下:

  1. 请求阶段
    • FilterA 记录请求日志。
    • FilterB 检查用户权限。
    • FilterC 设置字符编码。
    • 请求到达目标资源(如 Servlet 或 JSP)。
  2. 响应阶段
    • FilterC 完成响应处理。
    • FilterB 完成响应处理。
    • FilterA 记录响应日志。
    • 响应返回客户端。

过滤器链的注意事项

  • 执行顺序:过滤器的执行顺序非常重要,需要根据业务需求合理配置。
  • 性能影响:过滤器链中的每个过滤器都会增加请求处理的时间,因此应避免在过滤器中执行耗时操作。
  • 线程安全性:过滤器是单例的,多个请求会共享同一个过滤器实例,因此需要注意线程安全问题。

过滤器链的特点

  • 链式结构:请求和响应依次经过多个过滤器。
  • 配置灵活:可以通过注解或 XML 配置过滤器的执行顺序。
  • 功能解耦:将日志记录、权限验证、字符编码设置等功能分离到不同的过滤器中。

监听器(Listener)

监听器是 JavaWeb 中的一种重要组件,基于观察者模式实现,用于监听 Web 应用中的特定事件(如 ServletContextHttpSessionServletRequest 的创建、销毁和属性变化等)。通过监听器,我们可以在这些事件发生时执行特定的逻辑,通常用于以下场景:

  • 初始化资源:在应用启动时加载配置文件或初始化数据库连接。
  • 统计在线用户数:监听 Session 的创建和销毁,统计当前在线用户数。
  • 记录日志:在请求开始和结束时记录日志信息。
  • 清理资源:在应用关闭时释放资源。

监听器的分类

JavaWeb 中的监听器主要分为以下几类:

ServletContext 监听器

  • ServletContextListener:监听 ServletContext 的创建和销毁。
  • ServletContextAttributeListener:监听 ServletContext 中属性的添加、修改和删除。

HttpSession 监听器

  • HttpSessionListener:监听 HttpSession 的创建和销毁。
  • HttpSessionAttributeListener:监听 HttpSession 中属性的添加、修改和删除。
  • HttpSessionBindingListener:监听对象绑定到 Session 或从 Session 中解绑的事件。
  • HttpSessionActivationListener:监听 Session 的激活和钝化(在分布式环境中使用)。

ServletRequest 监听器

  • ServletRequestListener:监听 ServletRequest 的创建和销毁。
  • ServletRequestAttributeListener:监听 ServletRequest 中属性的添加、修改和删除。

监听器的使用步骤

  1. 实现监听器接口

创建一个类并实现相应的监听器接口,重写接口中的方法。

ServletContextListener

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

@WebListener
public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 应用启动时执行
        System.out.println("ServletContext initialized");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 应用关闭时执行
        System.out.println("ServletContext destroyed");
    }
}
  1. 配置监听器

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

  1. 注解配置:使用 @WebListener 注解(如上面的示例)。
  2. XML 配置:在 web.xml 中配置监听器。

XML 配置示例

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

常见监听器的使用示例

  1. ServletContextListener

用于监听 ServletContext 的创建和销毁,通常用于初始化和释放资源。

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

@WebListener
public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 应用启动时执行
        System.out.println("Application started");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 应用关闭时执行
        System.out.println("Application stopped");
    }
}
  1. HttpSessionListener

用于监听 HttpSession 的创建和销毁,通常用于统计在线用户数。

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    private int userCount = 0;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // Session 创建时执行
        userCount++;
        System.out.println("New session created. Online users: " + userCount);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // Session 销毁时执行
        userCount--;
        System.out.println("Session destroyed. Online users: " + userCount);
    }
}
  1. ServletRequestListener

用于监听 ServletRequest 的创建和销毁,通常用于记录请求日志。

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletRequestListener implements ServletRequestListener {

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        // 请求开始时执行
        System.out.println("Request started: " + sre.getServletRequest().getRemoteAddr());
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        // 请求结束时执行
        System.out.println("Request ended: " + sre.getServletRequest().getRemoteAddr());
    }
}

监听器的常见应用场景

  1. 初始化资源
    • 在应用启动时加载配置文件、初始化数据库连接池等。
  2. 统计在线用户数
    • 监听 Session 的创建和销毁,统计当前在线用户数。
  3. 记录日志
    • 在请求开始和结束时记录日志信息。
  4. 清理资源
    • 在应用关闭时释放资源,如关闭数据库连接、清理临时文件等。
  5. 权限控制
    • 监听 Session 的属性变化,检查用户权限。

监听器的注意事项

  • 性能影响
    • 监听器会在特定事件发生时触发,因此应避免在监听器中执行耗时操作。
  • 线程安全性
    • 监听器是单例的,多个事件会共享同一个监听器实例,因此需要注意线程安全问题。
  • 事件顺序
    • 监听器的执行顺序由 Web 容器决定,无法手动控制。

总结

监听器是 JavaWeb 中实现事件驱动编程的重要工具。通过监听器,我们可以在 Web 应用的生命周期中监听特定的事件,并执行相应的操作。以下是监听器的核心特点:

  1. 事件驱动:监听特定事件(如 ServletContextHttpSessionServletRequest 的创建、销毁和属性变化)。
  2. 功能丰富:支持多种类型的监听器,满足不同的业务需求。
  3. 配置灵活:可以通过注解或 XML 配置监听器。

相关文章:

  • 北京大学第五弹:《DeepSeek私有化部署和一体机》
  • Ubuntu-docker安装mysql
  • yoloV5训练visDrone2019-Det无人机视觉下目标检测
  • 开启焊接设备安全管控新纪元
  • 安装完flash-attn,使用时报错undefined symbol
  • Android View设置圆角方式大全
  • Vue3实战学习(Vue3的基础语法学习与使用(超详细))(3)
  • 【Linux】外接硬盘管理
  • Selenium库打开指定端口(9222、9333等)浏览器【已解决!!!】
  • 【JAVA架构师成长之路】【电商系统实战】第9集:订单超时关闭实战(Kafka延时队列 + 定时任务补偿)
  • 计算机视觉|MAE 的项目实战:从图像重建到目标检测
  • Maven的学习以及安装配置 2024/3/1 idea
  • python从入门到精通(二十二):python文件操作之Excel全攻略(基于pandas)
  • Django小白级开发入门
  • [网络爬虫] 动态网页抓取 — Selenium 介绍 环境配置
  • 速卖通商品详情API接口全解析
  • Vue3中动态Ref的魔法:绑定与妙用
  • 【已解决】error setting certificate verify locations
  • c++: 容器vector
  • 【SpringBoot3】使用Easy-Trans做字典翻译
  • 买了个服务器 怎么做网站/泰安seo推广
  • vps搭建vpn无法访问国内网站/十大广告公司
  • 做一手楼房的网站/廊坊seo网络推广
  • 联通营业厅做网站维护/网络推广是指什么
  • 做网站投注员挣钱吗/最近国际时事热点事件
  • 优秀甜品网站/百度网站推广关键词怎么查