spring OncePerRequestFilter 作用
是 Spring Web 提供的一个抽象滤器基类,用于保证在一次 HTTP 请求的整个分派过程中,该滤器仅执行一次,无论该请求经历了多少次内部转发(forward)、包含(include)或错误/异步分派。对于启用了 Servlet 3.0+ 异步支持的应用,如不希望在异步回调线程再次执行过滤逻辑,可重写。确定),若标记已存在则跳过,未标记则执行并打标记,确保同一次请求不会重复过滤 (子类在此方法
概要
OncePerRequestFilter 是 Spring Web 提供的一个抽象滤器基类,用于保证在一次 HTTP 请求的整个分派过程中,该滤器仅执行一次,无论该请求经历了多少次内部转发(forward)、包含(include)或错误/异步分派。它通过在请求属性中打标记来判断自身是否已执行过,并提供了一个只需关注业务逻辑的 doFilterInternal 方法,同时支持子类根据需要决定是否在错误或异步 dispatch 中跳过过滤。
核心作用与工作原理
-
保证单次执行
-
默认情况下,
OncePerRequestFilter会在过滤链开始时检查请求属性(属性名由getAlreadyFilteredAttributeName()确定),若标记已存在则跳过,未标记则执行并打标记,确保同一次请求不会重复过滤 (OncePerRequestFilter (Spring Framework 6.2.6 API), OncePerRequestFilter - Spring)。
-
-
简化子类实现
-
子类只需重写
doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain),聚焦业务逻辑,不必关心重复执行的问题 (OncePerRequestFilter (Spring Framework 6.2.6 API))。
-
-
异步与错误分派控制
-
默认
OncePerRequestFilter在普通、ERROR、ASYNC 三种 dispatch 类型中均执行过滤;子类可通过重写shouldNotFilterAsyncDispatch()或shouldNotFilterErrorDispatch()来排除异步或错误分派情形下的执行 (OncePerRequestFilter - Spring, Add the ability for OncePerRequestFilter to determine if it should ...)。
-
关键方法
-
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
实现了对“已过滤”标记的检查与设置,并最终调用doFilterInternal(...)或直接跳过。 -
protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
子类在此方法中编写实际的过滤逻辑(如认证、日志、头处理等),执行完成后必须调用filterChain.doFilter(request, response)以继续后续处理。 -
protected boolean shouldNotFilterAsyncDispatch()
返回true时会跳过在异步 dispatch 场景下的过滤,默认false。 -
protected boolean shouldNotFilterErrorDispatch()
返回true时会跳过在错误 dispatch 情形下的过滤,默认false。
常见使用场景
-
Spring Security 定制过滤器
Authentication、CSRF、Header 处理等安全相关过滤器通常继承自OncePerRequestFilter,确保安全检查仅执行一次,而不会因内部转发而重复认证 (Architecture :: Spring Security)。 -
请求日志与限流
在高并发场景下,通过自定义OncePerRequestFilter打印请求日志、记录链路或进行请求计数,避免重复记录导致数据冗余。 -
统一异常处理或上下文初始化
为每次请求初始化线程上下文、数据库连接或绑定 MDC(Mapped Diagnostic Context),并在请求结束前清理资源。
注意事项
-
务必调用
filterChain.doFilter
若漏写此调用,将导致后续过滤器及 Servlet 无法执行。 -
异步请求处理
对于启用了 Servlet 3.0+ 异步支持的应用,如不希望在异步回调线程再次执行过滤逻辑,可重写shouldNotFilterAsyncDispatch()返回true。 -
标记名称冲突
默认过滤标记名称与具体滤器实例名称相关,如有定制需求可重写getAlreadyFilteredAttributeName()。 -
注入与依赖
若在doFilterInternal中需注入 Spring Bean,请确保过滤器已通过 Spring 容器管理(如注册为@Component或在FilterRegistrationBean中声明),否则可能拿不到依赖(详见 StackOverflow 讨论) (Dependency Injection into Spring Servlet context ... - Stack Overflow)。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)