SpringMVC之过滤器(Filter)

一、概述

1.1 含义

过滤器是Web三大组件之一,也是项目中常用的工具。过滤器由Servlet提供,基于函数回调实现链式对网络请求和响应的拦截与修改。由于基于Servlet,几乎可以拦截Web服务器管理的所有资源(JSP、图片文件、HTML文件、CSS文件等)。

定义过滤器需要实现javax.servlet.Filter接口。过滤器不是Servlet,无法直接生成对客户端的响应,只能拦截已有请求并预处理不需要或不一致的信息资源。

1.2 流程原理

Web应用中,可以开发编写多个过滤器,这些过滤器组合称为过滤器链。用户发起请求后,请求信息会按过滤器链中过滤器的顺序依次进入每个过滤器。经过每层过滤器时,需通过过滤器的校验逻辑并放行才能进入下一层过滤器,直至服务器获取资源。服务器成功获取资源并响应过滤器后,会按反向顺序经过层层过滤器,最终响应用户。

1.3 分类

Servlet 2.5:

  • REQUEST: 用户直接访问页面时,WEB容器会调用过滤器链。
  • FORWARD: 通过RequestDispatcherforward访问目标资源时调用此过滤器。
  • INCLUDE: 通过RequestDispatcherinclude方法调用目标资源时调用。
  • ERROR: 通过声明式异常处理机制调用目标资源时调用过滤器链。

Servlet 3.0:

  • ASYNC: 支持异步处理。

二、定义过滤器

返回值类型 方法声明 描述
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 实现实际过滤操作。当客户端请求方法与过滤器设置的URL匹配时,Servlet容器会先调用过滤器的doFilter方法。FilterChain用于访问后续过滤器。
void init(FilterConfig filterConfig) Web应用启动时,Web服务器创建过滤器实例对象并调用其init方法完成对象初始化(过滤器对象仅创建一次,init方法仅执行一次)。开发者可通过init方法参数执行读取配置文件等初始化操作。
void destroy() Servlet容器销毁过滤器实例前调用此方法。用于释放过滤器占用的资源。
  • request: 代表客户端的请求对象。
  • response: 代表服务器向客户端发送的响应对象。
  • chain: 用于调用下一个Filter或目标ServletFilterChain对象。

三、使用过滤器

3.1 注解方式

创建步骤:

  1. 实现Filter接口,添加@WebFilter@Order注解配置过滤器:

    java 复制代码
    @Order(1)
    @WebFilter(filterName = "myFilter", urlPatterns = {"*"})
    public class MyCustomFilter1 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {}
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) {
            //TODO...
        }
    
        @Override
        public void destroy() {}
    }
  2. 在启动类添加@ServletComponentScan注解:

    java 复制代码
    @SpringBootApplication
    @ServletComponentScan
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

3.2 注册Bean方式

  1. 创建实现Filter接口的过滤器类:

    java 复制代码
    public class MyCustomFilter2 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) {
            //TODO...
        }
    
        @Override
        public void destroy() { }
    }
  2. 创建过滤器配置类,注册过滤器:

    java 复制代码
    @Configuration
    public class FilterConfig {
        @Bean
        public FilterRegistrationBean customFilter(){
            FilterRegistrationBean<MyCustomFilter2> filterBean = new FilterRegistrationBean<>();
            filterBean.setFilter(new MyCustomFilter2());
            filterBean.setName("myFilter");
            filterBean.addUrlPatterns("/*");
            return filterBean;
        }
    }

四、注解方式

4.1 参数说明

@WebFilter可配置多个参数,部分参数说明如下:

参数名称 参数类型 参数描述
description String 设置过滤器的描述信息
displayName String 要显示的过滤器名称
initParams WebInitParam\[\] 你可以在初始化时配置一些参数
filterName String 过滤器的名称
servletNames String\[\] 设置要过滤的Servlets
value String\[\] urlPatterns属性与urlPatterns属性的作用相同,两者都指定要拦截的路径
urlPatterns String\[\] 指定要拦截的路径
dispatcherTypes DispatcherType\[\] 设置过滤器过滤的请求类型。 支持以下属性:REQUEST(默认情况下,它过滤所有类型的请求), ASYNC, ERROR, FORWARD, INCLUDE
asyncSupported boolean 设置过滤器是否支持异步模式

4.2 使用示例

(1) 创建Controller类

java 复制代码
@RestController
public class TestController {

    @GetMapping("/a/hello")
    public String hello1() {
        return "hello world! a";
    }

    @GetMapping("/b/hello")
    public String hello2() {
        return "hello world! b";
    }

    @GetMapping("/c/hello")
    public String hello3() {
        return "hello world! c";
    }
}

(2) 创建过滤器类

java 复制代码
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"/a/*", "/b/*"}, description = "自定义过滤器")
public class MyCustomFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("请求处理前...");
        chain.doFilter(request, response);  // 放行请求
        System.out.println("请求处理后...");
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}

(3) 创建启动类

java 复制代码
@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

五、注册Bean方式

5.1 方法参数说明

方法名称 方法描述
setName() 设置过滤器的名称。
setFilter() 设置要注册的过滤器。
setOrder() 设置过滤器的顺序位置。
setAsyncSupported() 设置过滤器是否支持异步模式。
addUrlPatterns() 添加拦截的路径。
setUrlPatterns() 设置拦截的路径。
addServletNames() 添加过滤器的servlet名称。
setServletNames() 设置注册过滤器的servlet名称。
setInitParameters() 设置初始化参数。
addInitParameter() 添加初始化参数。
setMatchAfter() 设置是否在Servlet上下文中声明的任何过滤器映射之后匹配过滤器映射。
setDispatcherTypes() 设置过滤器过滤的请求类型。 支持的属性如下:REQUEST(默认情况下,它过滤所有类型的请求), ASYNC, ERROR, FORWARD, INCLUDE。

5.2 使用示例

(1) 创建Controller类

java 复制代码
@RestController
public class TestController {

    @GetMapping("/a/hello")
    public String hello1(){
        return"hello world! a";
    }

    @GetMapping("/b/hello")
    public String hello2(){
        return"hello world! b";
    }

    @GetMapping("/c/hello")
    public String hello3(){
        return"hello world! c";
    }
}

(2) 创建过滤器类

java 复制代码
public class MyCustomFilter1 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("请求处理前...");
        chain.doFilter(request, response);  // 放行请求
        System.out.println("请求处理后...");
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}

(3) 创建过滤器配置类

java 复制代码
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean customFilter() {
        FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
        filterBean.setFilter(new MyCustomFilter1());
        filterBean.setName("FilterController");
        filterBean.addUrlPatterns("/c/*", "/b/*");
        return filterBean;
    }
}

(4) 创建启动类

java 复制代码
@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

六、使用场景

  1. 日志记录
    过滤器可记录请求和响应的关键信息,便于排查问题和分析系统运行状态。例如记录请求URL、参数、响应状态码等。
  2. 数据统计
    用于采集各类数据指标,如统计请求次数、响应时间分布等,为系统优化提供依据。
  3. 数据格式转换
    不同系统交互时,过滤器可转换数据格式,例如将JSON转为XML
  4. 为数据设置默认值
    检查输入数据,为缺失字段设置默认值,保证数据完整性。
  5. 权限认证、黑白名单
    实现用户权限认证和访问控制,限制特定IP或用户的访问。
  6. 数据加解密、签名验证
    对敏感数据加解密以保证安全,同时进行签名验证确保数据完整性。
相关推荐
Zane19941 分钟前
daemon 线程说没就没?一文讲透 threading 的适用场景与线程安全
后端·python
凤山老林11 分钟前
从 RestTemplate 到 HttpClient 5:Spring Boot HTTP 客户端性能调优与连接池治理
spring boot·后端·http
Csvn13 分钟前
📊 SQL 入门 Day 20:锁机制
后端·sql
Code额1 小时前
Python 连接 DeepSeek API,OpenAI 对话方式总结
后端·python·ai·ai编程
星火10241 小时前
【LangChain4j系列10】Guardrails 安全护栏
人工智能·后端
四千岁1 小时前
稀疏向量BM25Retriever不支持中文怎么办?jieba来帮忙
前端·javascript·后端
用户6919026813391 小时前
Docker基本概念
后端·docker·容器
颜进强1 小时前
14 - OpenSpec 老页面改造骨架:定位 + 增量 + 回归三件套
前端·后端·ai编程
唐青枫1 小时前
别只把 switch 当成多路 if:Zig 模式匹配、状态机与 Tagged Union 实战
后端
步行cgn2 小时前
MyBatis 错误 Result Maps collection does not contain value for ... 详解与解决方案
后端