Spring Boot 3 中 WebFilter 的执行顺序流程分析

 更新时间:2025年08月09日 09:38:43   作者:牧云2800  
Spring Boot中管理WebFilter顺序,默认为Integer.MAX_VALUE,需显式使用@Order或Ordered接口定义优先级,请求阶段按顺序值从小到大执行,响应阶段按从大到小,相同顺序值依赖Bean注册顺序,本文详细说明在Spring Boot 3中如何管理这些过滤器的执行流程,需要的朋友一起看看吧

理解并控制 WebFilter 的执行顺序对于构建可预测、行为正确的 Web 应用至关重要。 本文详细说明在 Spring Boot 3 中如何管理这些过滤器的执行流程。

1. 默认执行顺序

  • 核心规则: 当开发者未显式指定任何顺序时,所有 WebFilter 实例的默认顺序值被统一设置为 Ordered.LOWEST_PRECEDENCE(其数值等于 Integer.MAX_VALUE),这意味着它们默认拥有最低的优先级,将在所有显式指定了顺序的过滤器之后执行。
  • 默认行为的影响: 在此默认顺序值下,多个过滤器的实际执行顺序由 Spring 容器中 Bean 的注册顺序 决定。这个顺序可能受到诸如类路径扫描(@ComponentScan)顺序或 @Bean 配置方法在配置类中的声明顺序等因素的影响。这种行为本质上是不可靠的,因为微小的代码变动或依赖更新都可能导致顺序意外改变,不应依赖于此进行关键逻辑控制。

2. 显式控制顺序的方法

为了确保执行顺序的确定性和可预测性,Spring 提供了两种主要机制来显式定义 WebFilter 的优先级。

2.1 使用@Order注解

通过在过滤器类上添加 @Order 注解并指定一个整数值,可以清晰定义其顺序。值越小,表示优先级越高,在请求处理阶段越早执行。

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@Component
@Order(1) // 明确指定顺序值为1(高优先级)
public class FilterA implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        System.out.println("FilterA (Order=1) - Before Logic"); // 在执行业务逻辑前
        return chain.filter(exchange) // 将请求传递到链中的下一个过滤器或处理器
                   .then(Mono.fromRunnable(() -> 
                          System.out.println("FilterA (Order=1) - After Logic"))); // 在业务逻辑执行后和响应发送前
    }
}

2.2 实现Ordered接口

让过滤器类实现 Ordered 接口并重写 getOrder() 方法是另一种等效且常用的方式。这种方式同样遵循数值越小优先级越高的原则

import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@Component
public class FilterB implements WebFilter, Ordered { // 同时实现WebFilter和Ordered接口
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        System.out.println("FilterB (Order=2) - Before Logic");
        return chain.filter(exchange)
                   .then(Mono.fromRunnable(() -> 
                          System.out.println("FilterB (Order=2) - After Logic")));
    }
    @Override
    public int getOrder() { // 实现Ordered接口要求的方法,返回定义的顺序值
        return 2; // 显式定义顺序值为2
    }
}

3. 执行顺序规则

Spring WebFlux 框架对 WebFilter 链的执行遵循明确的规则,区分请求处理(正向)和响应处理(反向)两个阶段:

  • 正向流程(请求处理阶段):
    当请求进入时,框架会按顺序值 从小到大(即优先级从高到低)依次调用每个 WebFilterfilter 方法中的 chain.filter(exchange) 之前的代码(即 “Before” 部分)。例如:@Order(1)@Order(2) → … → @Order(n)
  • 反向流程(响应处理阶段):
    当业务逻辑处理完毕,开始构建响应并向上返回时,框架会按顺序值 从大到小(即优先级从低到高)依次执行每个 WebFilterfilter 方法中 chain.filter(exchange).then(...) 里面的回调代码(即 “After” 部分)。例如:@Order(n) → … → @Order(2)@Order(1)

3.1 示例输出

结合 FilterA (Order=1) 和 FilterB (Order=2) 的代码,执行流程的日志输出清晰地展示了上述规则:

FilterA (Order=1) - Before Logic  // 最高优先级(1)最先处理请求
FilterB (Order=2) - Before Logic  // 次高优先级(2)接着处理请求
... (执行业务控制器逻辑) ...          // 实际业务处理
FilterB (Order=2) - After Logic   // 次高优先级(2)最先处理响应(反向)
FilterA (Order=1) - After Logic   // 最高优先级(1)最后处理响应(反向)

4. 特殊情况:相同顺序值

  • 行为规则: 如果两个或多个 WebFilter 被显式或隐式地赋予了相同的顺序值(例如都使用 @Order(5) 或都未指定而使用默认值 Integer.MAX_VALUE),则它们的执行顺序(包括正向和反向阶段)将退回到由 Spring 容器中 Bean 的注册顺序 决定,这通常等同于类加载顺序或 @Bean/@Component 的声明或扫描顺序。
  • 潜在风险与建议: 由于这种顺序在特定环境下可能不稳定,强烈建议开发者为所有需要特定执行位置的过滤器显式分配唯一且有意义的顺序值,避免依赖默认顺序或冲突的顺序值带来的不确定性。

5. 总结

控制方式实现示例执行顺序规则
@Order 注解@Order(1) 标注在 WebFilter 实现类上数值越小,在请求阶段越早执行
实现 Ordered 接口getOrder() 方法返回具体数值 (如 2)数值越小,在请求阶段越早执行
未指定顺序无注解或接口实现,默认 Integer.MAX_VALUE最后执行,具体顺序不稳定

最佳实践推荐:

  1. 始终显式指定顺序: 对于任何有依赖关系或执行位置要求的 WebFilter,务必使用 @Order 注解或实现 Ordered 接口来显式定义其顺序值(例如 @Order(100), @Order(200))。
  2. 规划顺序值范围: 为不同类型的过滤器预留顺序值区间(如认证用 0-99,日志用 100-199,安全后处理用 200-299),提升可读性和可维护性。
  3. 避免顺序冲突: 确保关键过滤器的顺序值唯一,防止因相同顺序值导致的不确定行为。

遵循这些实践能显著增强过滤器行为的可预测性和应用的健壮性

到此这篇关于Spring Boot 3 中 WebFilter 的执行顺序流程分析的文章就介绍到这了,更多相关Spring Boot WebFilter 执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot项目使用Flyway的详细教程

    Spring Boot项目使用Flyway的详细教程

    这篇文章主要介绍了Spring Boot项目使用Flyway,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Java中的static--静态变量你了解吗

    Java中的static--静态变量你了解吗

    Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问,.下面我们来详细了解一下吧
    2021-09-09
  • SpringBoot实现数据库读写分离的3种方法小结

    SpringBoot实现数据库读写分离的3种方法小结

    为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三种主实现方案,大家可以根据需要自行选择
    2025-04-04
  • 关于jpa中无法删除onetomany中many问题的解决

    关于jpa中无法删除onetomany中many问题的解决

    这篇文章主要介绍了关于jpa中无法删除onetomany中many问题的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java获取最后插入MySQL记录的自增ID值的3种方法

    Java获取最后插入MySQL记录的自增ID值的3种方法

    这篇文章介绍了Java获取最后插入MySQL记录的自增ID值的3种方法,有需要的朋友可以参考需要
    2013-08-08
  • SpringBoot实现敏感配置信息加密与解密

    SpringBoot实现敏感配置信息加密与解密

    SpringBoot支持多种配置加载方式,不管用哪种方式,敏感信息(比如数据库密码、Redis密码、第三方API密钥)如果明文存储,都会有泄露风险,下面我们就来聊聊如何对敏感配置信息加密与解密吧
    2025-07-07
  • Java 通过API操作GraphQL

    Java 通过API操作GraphQL

    这篇文章主要介绍了Java 通过API操作GraphQL的方法,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-05-05
  • SpringBoot应用是否存在MySQL连接泄漏问题的排查方法

    SpringBoot应用是否存在MySQL连接泄漏问题的排查方法

    这篇文章主要介绍了排查SpringBoot应用MySQL连接泄漏的方法,需检查连接数、空闲连接,配置连接池参数,确保资源关闭,并使用监控工具如Actuator和Prometheus分析,需要的朋友可以参考下
    2025-06-06
  • Java JVM中线程状态详解

    Java JVM中线程状态详解

    这篇文章主要介绍了Java JVM中线程状态详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的朋友可以参考一下
    2022-09-09
  • java的四种常用输入方法你会几种

    java的四种常用输入方法你会几种

    这篇文章主要介绍了java四种常用输入方法的相关资料,分别是Scanner、System、命令行和JOptionPane,每种方法都有其特点和适用场景,文中提供了详细的代码示例,需要的朋友可以参考下
    2025-03-03

最新评论