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 Security十分钟入门教程

    Spring Security十分钟入门教程

    这篇文章主要介绍了Spring Security入门教程,Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架
    2022-09-09
  • MyBatis Generator的简单使用方法示例

    MyBatis Generator的简单使用方法示例

    这篇文章主要给大家介绍了关于MyBatis Generator的简单使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Effective Java 在工作中的应用总结

    Effective Java 在工作中的应用总结

    《Effective Java》是一本经典的 Java 学习宝典,值得每位 Java 开发者阅读。下面文章即是将书中和平日工作较密切的知识点做了部分总结,需要的朋友可以参考下
    2021-09-09
  • JMeter自定义日志与日志分析的实现

    JMeter自定义日志与日志分析的实现

    JMeter与Java程序一样,会记录事件日志,本文就介绍一下JMeter自定义日志与日志分析的实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 使用JAVA实现http通信详解

    使用JAVA实现http通信详解

    本文给大家汇总介绍了几种java实现http通讯的方法,非常的简单实用,有需要的小伙伴可以参考下。
    2015-08-08
  • Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    下面小编就为大家分享一篇Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • SpringMVC中利用@InitBinder来对页面数据进行解析绑定的方法

    SpringMVC中利用@InitBinder来对页面数据进行解析绑定的方法

    本篇文章主要介绍了SpringMVC中利用@InitBinder来对页面数据进行解析绑定的方法,非常具有实用价值,需要的朋友可以参考下
    2018-03-03
  • SpringAOP如何修改请求参数列表

    SpringAOP如何修改请求参数列表

    这篇文章主要介绍了SpringAOP如何修改请求参数列表问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • java代理实现爬取代理IP的示例

    java代理实现爬取代理IP的示例

    今天小编就为大家分享一篇java代理实现爬取代理IP的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • MyBatis与Spring中的SqlSession详解

    MyBatis与Spring中的SqlSession详解

    在MyBatis中,你可以使用SqlSessionFactory来创建SqlSession,使用MyBatis-Spring之后,你不再需要直接使用SqlSessionFactory了,接下来通过示例代码讲解MyBatis与Spring中的SqlSession,需要的朋友可以参考下
    2024-05-05

最新评论