Spring Boot Filter 机制与 FilterRegistrationBean

一、 什么是 Filter(过滤器)?

Filter 是 Java Servlet 规范中最基础的组件之一。它像是一道 "关卡""筛子",位于客户端请求与后端 Servlet(Controller)之间。

1. 核心模型:责任链(Chain of Responsibility)

Web 服务器(如 Tomcat)维护了一条由多个 Filter 组成的 "链条"

  • 进门时(Request):请求必须依次通过 Filter A -> Filter B -> Filter C,最后才能到达 Controller。
  • 出门时(Response):Controller 返回的数据会反向通过 Filter C -> Filter B -> Filter A,最后回到客户端。

2. 核心方法:doFilter

所有的 Filter 必须实现 javax.servlet.Filter (Spring Boot 3.x 为 jakarta.servlet.Filter) 接口。

java 复制代码
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // --- 1. 前置处理 (Pre-processing) ---
    // 例如:记录请求开始时间、读取参数、设置编码
    System.out.println("请求进来了");

    // --- 2. 放行 (Pass) ---
    // 把请求传给下一个 Filter 或 Controller
    // ⚠️ 如果不写这一行,请求就会在这里断掉,永远到不了 Controller!
    chain.doFilter(request, response);

    // --- 3. 后置处理 (Post-processing) ---
    // 例如:计算耗时、修改响应头
    System.out.println("请求处理完了,准备返回");
}

二、 在 Spring Boot 中注册 Filter 的两种方式

在 Spring Boot 中,让一个 Filter 生效主要有两种方式:"自动挡""手动挡"

方式 1:自动挡(@Component)

适用场景 :逻辑简单、需要拦截所有请求(/*)、不需要精细控制顺序。

只要你的 Filter 类是一个 Spring Bean,Spring Boot 就会自动把它加入过滤器链。

java 复制代码
@Component // 1. 注册为 Bean
@Order(1)  // 2. (可选) 定义顺序
public class SimpleLogFilter implements Filter {
    @Override
    public void doFilter(...) {
        // ... 逻辑 ...
        chain.doFilter(request, response);
    }
}
  • 缺点 :默认拦截所有 URL,无法配置只拦截 /api/*

方式 2:手动挡(FilterRegistrationBean) 🌟🌟🌟

适用场景:需要控制拦截路径、需要精准控制顺序、或者 Filter 是第三方库提供的(没法加 @Component)。

这是大型项目(如 yudao)中最推荐的做法。


三、 FilterRegistrationBean 深度解析

FilterRegistrationBean 是 Spring Boot 提供的一个 "配置包装器" 。它不负责写业务逻辑,只负责 "管理" Filter。

你可以把它想象成 Filter 的 "入职合同",上面写明了:你负责哪个区域(URL)、你的工号是多少(Order)、你要不要上班(Enabled)。

1. 标准配置模板

通常在 @Configuration 类中定义:

java 复制代码
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<MyBizFilter> myBizFilterRegistration() {
        // 1. 创建注册器
        FilterRegistrationBean<MyBizFilter> registration = new FilterRegistrationBean<>();
        
        // 2. 注入真正的 Filter 实例 (可以是 new 的,也可以是 @Autowired 进来的)
        registration.setFilter(new MyBizFilter());
        
        // 3. 【核心】设置拦截规则
        // 只拦截 /api/ 下的请求,忽略 /static/ css js 等
        registration.addUrlPatterns("/api/*");
        
        // 4. 【核心】设置执行顺序
        // 数字越小越先执行。
        // Integer.MIN_VALUE 会排在最最前面
        registration.setOrder(10);
        
        // 5. 设置过滤器名称 (可选,用于日志显示)
        registration.setName("myBusinessFilter");
        
        // 6. 是否启用 (方便通过配置文件动态开关)
        registration.setEnabled(true);
        
        return registration;
    }
}

2. 关键属性详解

A. setFilter(Filter filter)
  • 作用:设置"谁"来干活。
  • 注意 :如果你在这里 new MyBizFilter(),请确保 MyBizFilter 类上没有 @Component 注解。否则 Spring 会注册两遍(一遍是自动扫描的全路径拦截,一遍是你配置的特定路径拦截)。
B. addUrlPatterns(String... patterns)
  • 作用:设置"管辖范围"。
  • 语法 :支持 * 通配符。
    • /*:拦截所有。
    • /api/*:拦截 api 目录。
    • *.html:拦截后缀。
C. setOrder(int order)
  • 作用:设置"排队顺序"。
  • 规则
    • 数值越 ,优先级越 (越早执行前置逻辑,越晚执行后置逻辑)。
    • 负数:通常用于系统级 Filter(如编码、跨域、日志追踪)。
    • 正数:通常用于业务级 Filter。

四、 Filter 的常见应用场景(不含 Security)

抛开 Spring Security,我们在工程中通常用 Filter 做以下基础设施工作:

  1. CORS 跨域处理 (CorsFilter)

    • 在请求头里加 Access-Control-Allow-Origin,解决前后端分离的跨域问题。通常排在前几名。
  2. 字符编码 (CharacterEncodingFilter)

    • 强制 Request 和 Response 使用 UTF-8。Spring Boot 默认已自动配置,排在最前面。
  3. 全链路追踪 (TraceIdFilter)

    • 在请求进来时生成一个唯一的 UUID (TraceId),放入 MDC (日志上下文)。
    • 这样后续所有的 log.info 都会带上这个 ID,方便排查问题。
  4. 请求日志记录 (RequestLoggingFilter)

    • 记录请求的 IP、URL、耗时、User-Agent 等信息。
  5. 多租户上下文初始化 (TenantContextFilter)

    • 从 Header 中提取 tenant-id,存入 ThreadLocal,供后续业务使用。

五、 总结

特性 Filter (自动挡 / @Component) FilterRegistrationBean (手动挡)
配置复杂度 低,加个注解就行 中,需要写 Java Config 代码
URL 控制 (默认全拦截) (支持 addUrlPatterns)
顺序控制 依赖 @Order 依赖 setOrder() (更直观)
第三方库支持 难 (无法改人家源码加注解) (直接 new 出来包装即可)
推荐指数 简单 Demo 推荐 企业级项目强力推荐
相关推荐
严文文-Chris2 小时前
RAG关键技术要点详解
java·服务器·前端
❀͜͡傀儡师2 小时前
基于docker一键部署 x86的cpu_mem_hog 用于生成CPU和内存负载,用于服务器cpu和内存使用不达标的
java·服务器·docker
蜡笔大新7982 小时前
IO流的认识(2)
java·ide·intellij-idea
bybitq2 小时前
Go-Package-Module-functions
开发语言·后端·golang
今晚务必早点睡2 小时前
Redis——快速入门第四课:Redis + Spring Boot 实战(从 0 到能用)
spring boot·redis·bootstrap
廋到被风吹走2 小时前
【Java】【JVM】OOM 原因、定位与解决方案
java·开发语言·jvm
苹果醋32 小时前
vue + iview + vue-i18n中英翻译
java·运维·spring boot·mysql·nginx
橙露2 小时前
VMware Workstation Pro 25H2的linux版本,免费分享,下载:全新命名体系 + 深度适配 Linux 内核,虚拟化效率拉满
java·linux·服务器
Miss_Chenzr2 小时前
Springboot文化艺术发展有限公司4rl42(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端