java web 过滤器

在 Java Web 开发中,过滤器(Filter)是 Servlet 规范中的一个重要组件,用于在请求到达 Servlet 之前或者响应返回客户端之前对请求和响应进行预处理或后处理。

过滤器的工作原理

过滤器的工作原理基于责任链模式。当客户端向服务器发送请求时,请求会先经过一系列过滤器,每个过滤器可以对请求进行修改、验证或拦截。请求依次通过过滤器链,最终到达目标 Servlet。当 Servlet 处理完请求并返回响应时,响应会按照相反的顺序再次经过这些过滤器,每个过滤器可以对响应进行修改或处理

过滤器的应用场景

  • 权限验证:检查用户是否有访问特定资源的权限。
  • 字符编码处理:统一设置请求和响应的字符编码,防止乱码问题。
  • 日志记录:记录请求的信息,如请求的 URL、参数等。
  • 敏感信息过滤:过滤请求中包含的敏感词汇。

过滤器的实现步骤

1. 实现 javax.servlet.Filter 接口

Filter 接口定义了三个方法:

  • init(FilterConfig filterConfig):在过滤器被创建时调用,用于初始化过滤器。
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain):对请求和响应进行处理的核心方法。
  • destroy():在过滤器被销毁时调用,用于释放资源。
java 复制代码
import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {

    private String encoding;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 从过滤器配置中获取字符编码
        encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null) {
            encoding = "UTF-8";
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 设置请求的字符编码
        request.setCharacterEncoding(encoding);
        // 设置响应的字符编码
        response.setCharacterEncoding(encoding);
        // 将请求和响应传递给下一个过滤器或目标 Servlet
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 可以在这里释放资源
    }
}

2. 配置过滤器

可以通过 web.xml 或注解的方式配置过滤器。

使用 web.xml 配置

XML 复制代码
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.example.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

使用注解配置(Servlet 3.0 及以上)

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = "/*", initParams = {
        @WebInitParam(name = "encoding", value = "UTF-8")
})
public class CharacterEncodingFilter implements Filter {

    private String encoding;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null) {
            encoding = "UTF-8";
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 可以在这里释放资源
    }
}

过滤器链

在一个 Web 应用中可以配置多个过滤器,这些过滤器会按照配置的顺序形成一个过滤器链。请求会依次通过过滤器链中的每个过滤器,响应则会按照相反的顺序返回。例如,有两个过滤器 FilterAFilterB,配置顺序为 FilterA 在前,FilterB 在后,那么请求的处理顺序为:FilterA -> FilterB -> Servlet,响应的处理顺序为:Servlet -> FilterB -> FilterA

注意事项

  • 过滤器是单例的,在整个 Web 应用的生命周期中只会创建一个实例。
  • 过滤器的 doFilter 方法中必须调用 FilterChaindoFilter 方法,否则请求将无法到达目标 Servlet。
  • init 方法中可以通过 FilterConfig 获取过滤器的初始化参数。
  • destroy 方法中可以释放过滤器占用的资源,如关闭数据库连接等。

实例:

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

// 使用 @WebFilter 注解配置过滤器,拦截所有请求
@WebFilter(filterName = "RequestLoggingFilter", urlPatterns = "/*")
public class RequestLoggingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 过滤器初始化方法,这里可以进行一些初始化操作,例如读取配置文件
        System.out.println("RequestLoggingFilter 初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 记录请求开始时间
        long startTime = System.currentTimeMillis();

        // 获取 HttpServletRequest 对象,以便获取请求的详细信息
        javax.servlet.http.HttpServletRequest httpRequest = (javax.servlet.http.HttpServletRequest) request;

        // 获取请求的 URL
        String requestUrl = httpRequest.getRequestURL().toString();
        // 获取请求的方法(如 GET、POST 等)
        String requestMethod = httpRequest.getMethod();

        System.out.println("开始处理请求: " + requestMethod + " " + requestUrl);

        try {
            // 将请求传递给下一个过滤器或目标 Servlet
            chain.doFilter(request, response);
        } finally {
            // 记录请求结束时间
            long endTime = System.currentTimeMillis();
            // 计算请求处理所花费的时间
            long processingTime = endTime - startTime;

            System.out.println("请求处理完成: " + requestMethod + " " + requestUrl + ",耗时: " + processingTime + " 毫秒");
        }
    }

    @Override
    public void destroy() {
        // 过滤器销毁方法,这里可以进行一些资源释放操作
        System.out.println("RequestLoggingFilter 销毁");
    }
}    
  1. 注解配置@WebFilter(filterName = "RequestLoggingFilter", urlPatterns = "/*") 此注解将该类配置为过滤器,filterName 是过滤器的名称,urlPatterns = "/*" 表示该过滤器会拦截所有的请求。
  2. init 方法:在过滤器初始化时被调用,可用于执行一些初始化操作,例如读取配置文件。
  3. doFilter 方法 :这是过滤器的核心方法,其主要工作如下:
    • 记录请求开始时间。
    • ServletRequest 转换为 HttpServletRequest,从而获取请求的详细信息。
    • 输出请求的 URL 和请求方法。
    • 调用 chain.doFilter(request, response) 把请求传递给下一个过滤器或者目标 Servlet。
    • 计算请求处理所花费的时间并输出。
  4. destroy 方法:在过滤器销毁时被调用,可用于释放资源。
相关推荐
fs哆哆5 分钟前
在VB.net中,用正则表达式方法清除干扰符号方法
开发语言·正则表达式·c#·.net
麦兜*18 分钟前
【为什么RabbitMQ能够控制事务?控制事务的原理】
java·rabbitmq·java-rabbitmq
嵌入式@秋刀鱼19 分钟前
《 第三章-招式初成》 C++修炼生涯笔记(基础篇)程序流程结构
linux·开发语言·数据结构·c++·笔记·visual studio code
温温top19 分钟前
java中合并音频
java·音视频
shenyan~28 分钟前
关于 WASM: WASM + JS 混合逆向流程
开发语言·javascript·wasm
九转苍翎28 分钟前
Java SE(13)——工具类
java·工具类
小马爱打代码33 分钟前
数据结构 - Java 队列
java·数据结构
梦境虽美,却不长1 小时前
C语言 学习 文件操作(开关,读写,定位,大小)操作 2025年6月8日12:19:24
c语言·开发语言·学习
Charlotte_jc1 小时前
完美解决openpyxl保存Excel丢失图像/形状资源的技术方案
开发语言·python·excel·openpyxl
盖世英雄酱581361 小时前
🚀不改SQL,也能让SQL的执行效率提升100倍
java·数据库·后端