过滤器

过滤器

过滤器基本概念

  • 过滤器(Filter) 是一种用于在请求到达目标资源(如 Servlet、JSP)之前或响应返回客户端之前执行某些操作的组件。
  • Tomcat 作为 Java Web 服务器,完全支持 Servlet 规范中的过滤器机制。过滤器通常用于实现以下功能:
    • 日志记录:记录请求和响应的详细信息。
    • 权限验证:检查用户是否有权限访问某些资源。
    • 数据压缩:对响应数据进行压缩。
    • 字符编码转换:统一请求和响应的字符编码。
    • 跨域处理:设置跨域请求头

过滤器工作原理

  • 过滤器是基于 责任链模式 实现的。多个过滤器可以形成一个链,请求和响应会依次经过这些过滤器,最后到达目标资源。
  • 过滤器的工作流程如下:
    • 客户端发送请求
    • 请求经过过滤器链
      • 每个过滤器可以对请求进行处理(如修改请求头、验证权限等)。
    • 请求到达目标资源(如 Servlet 或 JSP)。
    • 响应经过过滤器链
      • 每个过滤器可以对响应进行处理(如修改响应头、压缩数据等)。
    • 响应返回客户端

过滤器核心接口

  • 过滤器是通过实现 javax.servlet.Filter 接口来创建的。
  • 该接口定义了以下三个方法
    • void init(FilterConfig filterConfig)
      • 作用:初始化过滤器。
      • 参数
        • filterConfig:提供过滤器的配置信息。
      • 调用时机:在 Web 应用启动时调用。
    • void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      • 作用:执行过滤逻辑。
      • 参数
        • request:客户端请求对象。
        • response:服务器响应对象。
        • chain:过滤器链,用于调用下一个过滤器或目标资源。
      • 调用时机:每次请求经过过滤器时调用。
    • void destroy()
      • 作用:销毁过滤器。
      • 调用时机:在 Web 应用关闭时调用。

过滤器的配置

使用 web.xml 配置

  • web.xml 中定义过滤器和过滤器映射:

  • <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>com.example.MyFilter</filter-class>
        <init-param>
            <param-name>param1</param-name>
            <param-value>value1</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <servlet-name>demo01</servlet-name>
    </filter-mapping>
    
    • <url-pattern>:指定过滤器应用的 URL 模式。

    • <servlet-name>:指定过滤器应用的 Servlet 名称。

      • <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>com.example.MyServlet</servlet-class>
        </servlet>
        
      • @WebServlet(name = "MyServlet", urlPatterns = {"/my-servlet"})
        public class MyServlet extends HttpServlet {
            // Servlet 的实现代码
        }
        
    • 可以对应多个URL模式或者Servlet名称

使用注解配置

  • 在过滤器类上使用 @WebFilter 注解:

  • @WebFilter(
        filterName = "MyFilter",
        urlPatterns = "/*",
        initParams = {
            @WebInitParam(name = "param1", value = "value1")
        }
    )
    public class MyFilter implements Filter {
        // 过滤器实现
    }
    

过滤器的示例代码

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

@WebFilter(urlPatterns = "/*")
public class LoggingFilter implements Filter {

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        long startTime = System.currentTimeMillis();

        // 记录请求 URL
        String requestUrl = ((HttpServletRequest) request).getRequestURL().toString();
        System.out.println("Request URL: " + requestUrl);

        // 调用下一个过滤器或目标资源
        chain.doFilter(request, response);

        // 记录处理时间
        long endTime = System.currentTimeMillis();
        System.out.println("Request processed in " + (endTime - startTime) + " ms");
    }

    @Override
    public void destroy() {
        // 销毁逻辑
        System.out.println("LoggingFilter destroyed.");
    }
}

过滤器的常见应用场景

  • 权限验证

    • 在过滤器中检查用户是否已登录或具有访问权限。
    • 如果未通过验证,可以重定向到登录页面或返回错误响应。
  • 字符编码转换

    • 在过滤器中统一设置请求和响应的字符编码。

    • request.setCharacterEncoding("UTF-8");
      response.setCharacterEncoding("UTF-8");
      
  • 数据压缩

    • 在过滤器中压缩响应数据,减少网络传输量。

    • response.setHeader("Content-Encoding", "gzip");
      
  • 跨域处理

    • 在过滤器中设置跨域请求头,支持跨域请求。

    • response.setHeader("Access-Control-Allow-Origin", "*");
      response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
      response.setHeader("Access-Control-Allow-Headers", "Content-Type");
      

过滤器执行顺序

  • web.xml 中,过滤器的执行顺序由 <filter-mapping> 标签的声明顺序决定。
    • 先声明的过滤器先执行
  • 如果使用 @WebFilter 注解配置过滤器,执行顺序由过滤器的类名(按字母顺序)决定。
    • 不是通过 @WebFilter 注解中的 filterName 属性来决定的
    • 类名按字母顺序排列,靠前的过滤器先执行
  • 混合配置的顺序
    • 如果同时使用 web.xml@WebFilter 注解配置过滤器,web.xml 中配置的过滤器优先执行。
    • web.xml 中的过滤器 > 注解配置的过滤器

过滤器的生命周期

  • 过滤器是单例的,即 Web 容器只会为每个过滤器类创建一个实例
  • 这意味着过滤器的 doFilter 方法可能会被多个线程同时调用,因此必须确保 doFilter 方法是线程安全的
  • Web 容器通过反射机制调用过滤器的默认构造方法创建实例
  • 创建实例后,Web 容器会调用 init 方法完成初始化
  • 生命周期如下
    • 实例化
      • Web 容器调用过滤器的构造方法创建实例。
      • 这是过滤器的第一个生命周期阶段。
    • 初始化(Initialization)
      • 过滤器在 Web 应用启动时或第一次被请求时初始化。
      • 初始化阶段会调用过滤器的 init 方法。
    • 执行(Execution)
      • 每次请求经过过滤器时,都会调用过滤器的 doFilter 方法。
      • 过滤器可以对请求和响应进行处理,并决定是否将请求传递给下一个过滤器或目标资源。
    • 销毁(Destruction)
      • 过滤器在 Web 应用关闭时或过滤器被移除时销毁。
      • 销毁阶段会调用过滤器的 destroy 方法。
posted @ 2025-03-18 15:24  QAQ001  阅读(113)  评论(0)    收藏  举报