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 方法:在过滤器销毁时被调用,可用于释放资源。
相关推荐
Kairo_019 分钟前
在 API 模拟阶段:Apipost vs. Faker.js vs. Postman —— 为什么 Apipost 是最优选择
开发语言·javascript·postman
Once_day20 分钟前
研发效率破局之道阅读总结(4)个人效率
开发语言·研发效能·devops
xcLeigh20 分钟前
HTML5好看的水果蔬菜在线商城网站源码系列模板8
java·前端·html5
痕51720 分钟前
如何在idea中写spark程序。
开发语言
Alsn8631 分钟前
11.Spring Boot 3.1.5 中使用 SpringDoc OpenAPI(替代 Swagger)生成 API 文档
java·spring boot·后端
liyongjun631638 分钟前
Java List分页工具
java·后端
橙子199110161 小时前
请简述一下什么是 Kotlin?它有哪些特性?
android·开发语言·kotlin
猎人everest1 小时前
Spring Boot集成Spring Cloud 2024(不使用Feign)
java·spring boot·spring cloud
martian6651 小时前
信创系统图形界面开发指南:技术选择与实践详解
开发语言·科技·系统架构·系统安全·创业创新
我命由我123451 小时前
STM32 开发 - stm32f10x.h 头文件(内存映射、寄存器结构体与宏、寄存器位定义、实现点灯案例)
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·嵌入式