Spring Boot 中 Filter 过滤器详解

目录

  • [1. 什么是 Filter?](#1. 什么是 Filter?)
  • [2. Filter 的作用](#2. Filter 的作用)
    • [2.1 身份认证](#2.1 身份认证)
    • [2.2 权限校验](#2.2 权限校验)
    • [2.3 请求日志](#2.3 请求日志)
    • [2.4 全局 Header 处理](#2.4 全局 Header 处理)
    • [2.5 防跨域 CORS](#2.5 防跨域 CORS)
    • [2.6 安全防护](#2.6 安全防护)
  • [3. Filter 基本使用](#3. Filter 基本使用)
  • [4. Filter 的注册方式](#4. Filter 的注册方式)
    • [4.1 @Component 注册](#4.1 @Component 注册)
    • [4.2 FilterRegistrationBean 注册](#4.2 FilterRegistrationBean 注册)
    • [4.3 Spring Security 注册排序 Filter](#4.3 Spring Security 注册排序 Filter)
  • [5. OncePerRequestFilter 是什么?](#5. OncePerRequestFilter 是什么?)
    • [5.1 防止重复执行](#5.1 防止重复执行)
    • [5.2 提供 shouldNotFilter()](#5.2 提供 shouldNotFilter())
  • [6. 多个 Filter 如何执行?](#6. 多个 Filter 如何执行?)
  • [7. Filter 顺序如何指定?](#7. Filter 顺序如何指定?)
    • [7.1 @Order](#7.1 @Order)
    • [7.2 FilterRegistrationBean](#7.2 FilterRegistrationBean)
    • [7.3 Spring Security Filter](#7.3 Spring Security Filter)
  • [8. Spring Security Filter Chain](#8. Spring Security Filter Chain)
  • [9.注意:不要把同一个 Filter 注册两次](#9.注意:不要把同一个 Filter 注册两次)
  • [10. Filter、Interceptor、AOP 区别](#10. Filter、Interceptor、AOP 区别)
    • [10.1 执行位置不同](#10.1 执行位置不同)
    • [10.2 对比表](#10.2 对比表)
  • [11. 什么场景适合 Filter?](#11. 什么场景适合 Filter?)
    • [11.1 JWT认证](#11.1 JWT认证)
    • [11.2 网关安全](#11.2 网关安全)
    • [11.3 全局处理](#11.3 全局处理)
  • [12. 什么情况更适合 Interceptor?](#12. 什么情况更适合 Interceptor?)
  • [13. Filter 与 Interceptor 实际组合](#13. Filter 与 Interceptor 实际组合)
  • [14. 完整示例:三个 Filter 按顺序执行](#14. 完整示例:三个 Filter 按顺序执行)
    • [第一个 Filter](#第一个 Filter)
    • [第二个 Filter](#第二个 Filter)
    • [第三个 Filter](#第三个 Filter)
  • [15. Filter 核心知识总结图](#15. Filter 核心知识总结图)
  • [16. 一句话总结](#16. 一句话总结)

1. 什么是 Filter?

在 Java Web 开发中,Filter(过滤器)是 Servlet 规范提供的一种请求拦截机制

它可以在:

  • 请求进入 Controller 之前
  • 响应返回客户端之前

对 HTTP 请求和响应进行统一处理。

简单理解:

Filter 就像 Web 请求进入系统前的一道"门卫",所有请求必须经过它检查,然后决定是否继续向后执行。

一个 HTTP 请求完整流程:

复制代码
	客户端请求
        ↓
     Filter
        ↓
DispatcherServlet
        ↓
	Controller
        ↓
	Service
        ↓
	  数据库
        ↓
	响应返回
        ↓
     Filter
        ↓
	 客户端

2. Filter 的作用

Filter 最常见用途:

2.1 身份认证

例如:

  • JWT Token 校验
  • 登录状态检查
  • 用户身份解析

示例:

java 复制代码
String token = request.getHeader("Authorization");

if(token == null){
    response.setStatus(401);
    return;
}

2.2 权限校验

例如:

复制代码
用户访问:

/admin/user/delete

Filter 判断:

复制代码
当前用户
    |
    |
是否拥有删除权限?

没有权限:

复制代码
403 Forbidden

2.3 请求日志

统一记录:

  • 请求 URL
  • 请求参数
  • 用户信息
  • 请求耗时

例如:

复制代码
request start

/api/order/query

cost 120ms

2.4 全局 Header 处理

例如:

统一添加:

复制代码
X-Request-ID
Trace-ID

方便链路追踪。


2.5 防跨域 CORS

例如:

处理:

复制代码
Access-Control-Allow-Origin

2.6 安全防护

例如:

  • XSS 防护
  • SQL 注入检测
  • Response Header 安全设置

3. Filter 基本使用

Servlet 原生 Filter:

java 复制代码
public class MyFilter implements Filter {

    @Override
    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) 
        										throws IOException, ServletException {

        System.out.println("请求进入 Filter");

        //继续执行后面的 Filter
        chain.doFilter(request,response);


        System.out.println("响应离开 Filter");

    }

}

重点:

java 复制代码
chain.doFilter(request,response);

表示:

当前 Filter 处理完成,继续执行后续流程。

如果不调用:

java 复制代码
chain.doFilter()

请求会直接结束。

例如:

java 复制代码
if(token非法){

    response.setStatus(401);

    return;
}

流程:

复制代码
Request

 ↓

AuthenticationFilter

 ↓

Token失败

 ↓

返回401

 ↓

Controller不会执行

4. Filter 的注册方式

定义 Filter 并不会自动生效。

必须注册。

常见有三种方式。


4.1 @Component 注册

java 复制代码
@Component
public class LoginFilter  extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain)throws IOException, ServletException {

        System.out.println("Login Filter");


        filterChain.doFilter(request,response);

    }
}

Spring Boot 启动:

复制代码
扫描 Bean

↓

发现 Filter

↓

注册到 Servlet Filter Chain

缺点:

默认所有请求都会经过。


4.2 FilterRegistrationBean 注册

更加灵活。

java 复制代码
@Configuration
public class FilterConfig {


    @Bean
    public FilterRegistrationBean<LoginFilter> loginFilter(){


        FilterRegistrationBean<LoginFilter> bean =
                new FilterRegistrationBean<>();


        bean.setFilter(new LoginFilter());


        //过滤路径
        bean.addUrlPatterns("/api/*");


        //执行顺序
        bean.setOrder(1);


        return bean;
    }

}

效果:

复制代码
/api/*
    ↓
LoginFilter


/static/*
    ↓
不经过

4.3 Spring Security 注册排序 Filter

Spring Security 一般不要靠:

java 复制代码
@Order

排列 Security Filter。

而应该:

java 复制代码
addFilterBefore
java 复制代码
addFilterAfter
java 复制代码
addFilterAt

例如:

java 复制代码
//注册 jwtFilter 放到 UsernamePasswordAuthenticationFilter 前,也就是 jwtFilter 先执行
http.addFilterBefore(
    jwtFilter,
    UsernamePasswordAuthenticationFilter.class
);

意思:

tex 复制代码
JwtFilter
 ↓
UsernamePasswordAuthenticationFilter

或者:

java 复制代码
//注册 logFilter 放到 AuthenticationFilter 后,也就是 AuthenticationFilter 先执行
http.addFilterAfter(
    logFilter,
    AuthenticationFilter.class
);

意思:

tex 复制代码
AuthenticationFilter
 ↓
LogFilter

完整示例,在企业项目中,认证相关 Filter 最常见方式:

加入 Spring Security Filter Chain。

例如:

java 复制代码
@Configuration
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http, JwtFilter jwtFilter) throws Exception {

        http.addFilterBefore(
                jwtFilter,
                UsernamePasswordAuthenticationFilter.class
        );


        return http.build();
    }

}

执行:

复制代码
JwtFilter

 ↓

UsernamePasswordAuthenticationFilter

常用于:

  • JWT
  • OAuth2
  • 内部接口认证
  • 签名验证

5. OncePerRequestFilter 是什么?

Spring 提供:

复制代码
OncePerRequestFilter

用于解决:

一个请求只执行一次 Filter。

例如:

你有 LoginFilter 和 JwtAuthenticationFilter ,它们都 继承 OncePerRequestFilter:

java 复制代码
@Component
public class LoginFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain)throws ServletException, IOException {

        System.out.println("LoginFilter");

        filterChain.doFilter(request,response);
    }

}


@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal( HttpServletRequest request,HttpServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {

        log.info("JWT认证");

        filterChain.doFilter(request,response);

    }

}

如果两个 Filter 都注册成功:

tex 复制代码
Spring Security Filter Chain
        |
        ↓
  LoginFilter 执行一次
        ↓
JwtAuthenticationFilter 执行一次
        ↓
  Controller

OncePerRequestFilter 的"一次"是什么意思?

它不是:

错误理解:一个请求只能执行一个 OncePerRequestFilter

而是:

正确理解:同一个 OncePerRequestFilter 实例,对于同一次 HTTP 请求,只执行一次。

继承关系:

复制代码
Filter

  ↓

GenericFilterBean

  ↓

OncePerRequestFilter

  ↓

自己的Filter

通常 Spring Boot 项目不会直接实现:

java 复制代码
Filter

而是:

java 复制代码
extends OncePerRequestFilter

优势:

5.1 防止重复执行

某些情况下:

  • forward
  • include
  • error dispatch

可能导致 Filter 多次执行。

OncePerRequestFilter 会保证:

复制代码
一次HTTP请求

	↓

Filter只执行一次

5.2 提供 shouldNotFilter()

例如:

只过滤:

复制代码
/api/*
@Override
protected boolean shouldNotFilter(
        HttpServletRequest request){


    return !request
            .getRequestURI()
            .startsWith("/api");

}

6. 多个 Filter 如何执行?

实际项目中通常有多个 Filter:

例如:

复制代码
TraceIdFilter
	↓
CorsFilter
	↓
AuthenticationFilter
	↓
AuthorizationFilter
	↓
ResponseFilter
	↓
Controller

Filter 是一个链:

复制代码
Filter1
	↓
Filter2
	↓
Filter3
	↓
Controller
	↓
Filter3
	↓
Filter2
	↓
Filter1

类似:

复制代码
洋葱模型

7. Filter 顺序如何指定?

7.1 @Order

java 复制代码
@Component
@Order(1)
public class LogFilter extends OncePerRequestFilter {

}
@Component
@Order(2)
public class AuthFilter  extends OncePerRequestFilter {

}

执行:

复制代码
LogFilter
	↓
AuthFilter
	↓
Controller

规则:

复制代码
数字越小,优先级越高

7.2 FilterRegistrationBean

java 复制代码
bean.setOrder(1);

7.3 Spring Security Filter

推荐:

java 复制代码
addFilterBefore()

addFilterAfter()

addFilterAt()

例如:

java 复制代码
http.addFilterBefore(
        jwtFilter,
        UsernamePasswordAuthenticationFilter.class
);

表示:

复制代码
jwtFilter
	↓
UsernamePasswordAuthenticationFilter

8. Spring Security Filter Chain

Spring Security 本身也是通过 Filter 实现。

整体:

复制代码
HTTP Request
      ↓
DelegatingFilterProxy
      ↓
FilterChainProxy
      ↓
Spring Security Filters
      ↓
DispatcherServlet
      ↓
Controller

例如:

复制代码
SecurityContextFilter
	↓
JwtAuthenticationFilter
	↓

AuthorizationFilter
	↓
Controller

9.注意:不要把同一个 Filter 注册两次

这是项目里很常见的坑。

假设:

java 复制代码
@Component
public class AuthenticationFilter
        extends OncePerRequestFilter {
}

然后又:

java 复制代码
http.addFilterBefore(
    authenticationFilter,
    UsernamePasswordAuthenticationFilter.class
);

有可能造成这个 Filter:

tex 复制代码
既作为 Servlet Filter 注册

又进入 Spring Security Filter Chain

从设计上就重复了。

虽然:

java 复制代码
OncePerRequestFilter

有"一次请求一次执行"的保护机制,但依然不建议这么做。

Security Filter 通常推荐:

java 复制代码
@Bean
public AuthenticationFilter authenticationFilter() {
    return new AuthenticationFilter(...);
}

然后:

java 复制代码
http.addFilterBefore(...)

而不是同时:

java 复制代码
@Component

java 复制代码
addFilterBefore()

10. Filter、Interceptor、AOP 区别

这是 Java Web 中非常经典的问题。

10.1 执行位置不同

复制代码
HTTP请求
  ↓
Filter
  ↓
DispatcherServlet
  ↓
Interceptor
  ↓
Controller
  ↓
 AOP
  ↓
Service

10.2 对比表

对比 Filter Interceptor AOP
所属规范 Servlet Spring MVC Spring
作用范围 HTTP请求 Controller方法 Java方法
能否获取请求 可以 可以 通常不直接
能否获取Controller信息 不方便 可以 不可以
执行位置 最前面 Controller之前 方法调用
典型用途 认证、安全、日志 权限、参数校验 事务、日志
技术 所在层级 能处理什么
Filter Servlet 层 HTTP 请求
Interceptor Spring MVC 层 Controller 请求
AOP Spring Bean 层 方法调用

11. 什么场景适合 Filter?

适合:

11.1 JWT认证

复制代码
 请求
  ↓
解析Token
  ↓
设置用户信息
  ↓
Controller

11.2 网关安全

例如:

  • API签名
  • 时间戳校验
  • 防重放攻击

11.3 全局处理

例如:

  • TraceId
  • 日志
  • CORS
  • Header

12. 什么情况更适合 Interceptor?

Interceptor 更了解 Spring MVC。

例如:

Controller:

java 复制代码
@GetMapping("/order")
@Permission("ORDER_QUERY")
public Order query(){

}

Interceptor 可以:

java 复制代码
HandlerMethod method

获取:

java 复制代码
@Permission

然后判断权限。

所以:

适合:

  • Controller权限
  • 注解鉴权
  • 登录用户操作限制

13. Filter 与 Interceptor 实际组合

企业项目通常:

复制代码
Filter 负责:用户是谁?Token是否合法?
	↓
Interceptor 负责:用户有没有权限访问这个接口?
	↓
Controller
	↓
Service
	↓
 AOP 负责:事务、日志

14. 完整示例:三个 Filter 按顺序执行

第一个 Filter

java 复制代码
@Component
@Order(1)
public class LogFilter extends OncePerRequestFilter {


    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain)throws IOException, ServletException {

        System.out.println("Log before");

        chain.doFilter(request,response);

        System.out.println("Log after");

    }

}

第二个 Filter

java 复制代码
@Component
@Order(2)
public class AuthenticationFilter extends OncePerRequestFilter {

    protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response,
            FilterChain chain)throws IOException, ServletException {

        System.out.println("Auth before");

        chain.doFilter(request,response);


        System.out.println("Auth after");

    }

}

第三个 Filter

java 复制代码
@Component
@Order(3)
public class TraceFilterextends OncePerRequestFilter {

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        System.out.println("Trace before");

        chain.doFilter(request,response);

        System.out.println("Trace after");

    }

}

Controller:

java 复制代码
@GetMapping("/test")
public String test(){

    System.out.println("Controller");

    return "success";
}

执行结果:

复制代码
Log before

Auth before

Trace before


Controller


Trace after

Auth after

Log after

原因:

Filter 是嵌套调用模型:

复制代码
Log

  Auth

    Trace

       Controller

    Trace

  Auth

Log

15. Filter 核心知识总结图

复制代码
                         HTTP Request
                               |
                               ↓
                    +----------------+
                    |     Filter     |
                    +----------------+
                               |

        +----------------------+----------------+
        |                      |                |

        ↓                      ↓                ↓

    Authentication          Log/Trace          Security


    JWT Token              RequestId          CORS

    权限验证               请求日志            Header处理

                               |
                               ↓
                       DispatcherServlet
                               |
                               ↓
                         Interceptor
                               |
                               ↓
                           Controller
                               |
                               ↓
                              AOP
                               |
                               ↓
                            Service

16. 一句话总结

Filter 是 Servlet 层面的请求拦截器,负责处理进入系统的 HTTP 请求;

Spring Boot 中通常通过 @ComponentFilterRegistrationBean 或 Spring Security 的 addFilterBefore/addFilterAfter 注册;

企业项目中认证、安全类逻辑优先使用 Filter,而 Controller 级别的权限控制更适合使用 Interceptor,业务方法增强则使用 AOP。


相关推荐
SemiTris1 小时前
为什么 C/C++ 不走 Java 式的虚拟机跨平台路线?
java·程序员
予怀9601 小时前
ClickHouse踩坑:一个sum()引发的"数字不一致"悬案
后端
橘色的喵1 小时前
ReclaimBatcher 批量回收:RT-Thread 单核与 Linux SMP 通用
后端
weixin_440784112 小时前
【IntentSeivice实现原理】
android·java·开发语言·intentservice
攻城有术2 小时前
专项攻克-springcloud及其组件
后端·spring·spring cloud
IanSkunk2 小时前
企业AI Agent生产化落地:从技术架构到实施服务的全链路分析
java·人工智能·架构
岁岁养乐多2 小时前
Java 序列化相关问题
java·开发语言
小短腿乄3 小时前
java实现pdf加水印+签名
java·开发语言·pdf