OncePerRequestFilter

OncePerRequestFilter是Spring框架提供的一个过滤器基类,它的核心作用是‌确保在一次完整的HTTP请求中,过滤器的逻辑只会被执行一次‌,即使请求在服务器内部经过了多次转发或包含多个资源请求‌23。

🔍 核心原理

OncePerRequestFilter通过内部机制跟踪当前请求是否已经被处理过:

  • 使用HttpServletRequest的getAttribute和setAttribute方法
  • 结合ThreadLocal变量来标记请求状态
  • 首次请求时执行过滤器逻辑并设置标记,后续直接跳过‌3

⚡ 与普通Filter的区别

特性 Filter OncePerRequestFilter
执行次数 可能多次执行 保证仅执行一次
来源 Servlet容器规范 Spring框架提供
适用场景 基础过滤需求 需要精确控制过滤次数的场景‌4

💡 为什么需要OncePerRequestFilter?

主要有两个原因:

  1. 适配不同Web容器‌:并非所有容器都保证过滤器只执行一次‌2
  2. 兼容异步请求‌:Servlet 3.0+中,异步分发可能导致过滤器重复执行‌2

🛠️ 使用示例

java 复制代码
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TimingFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   FilterChain filterChain) 
            throws ServletException, IOException {
        
        // 记录请求开始时间
        long startTime = System.currentTimeMillis();
        
        // 继续过滤器链
        filterChain.doFilter(request, response);
        
        // 记录请求处理时间
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        System.out.println("Request took " + duration + " ms to process");
    }
}

📚 实践建议

在Spring环境下开发过滤器时,推荐继承OncePerRequestFilter而不是直接实现Filter接口‌‌2。这样可以避免因容器差异导致的重复执行问题,确保过滤器逻辑的可靠性。

建议‌:在你的下一个Spring项目中,将自定义过滤器改为继承OncePerRequestFilter,这样可以避免潜在的重复处理问题,提升应用的稳定性。

相关推荐
星辰徐哥15 分钟前
异步定时任务系统的设计与Rust实战集成
开发语言·后端·rust
海兰43 分钟前
【springboot】gradle快速镜像配置
spring boot·笔记·后端
武超杰1 小时前
SpringBoot 整合 Spring Security 实现权限控制
spring boot·后端·spring
XMYX-01 小时前
06 - Go 的切片、字典与遍历:从原理到实战
后端·golang
架构师专栏1 小时前
比 MQ 更轻的异步方案:Spring 内置的这个隐藏功能,很多人还不知道
后端
林木881 小时前
Druid Kafka 数据源消费到 Segment 生成全链路深度分析
后端
摇曳的精灵1 小时前
Spring boot注解实现信息脱敏
java·spring boot·后端·注解脱敏·信息脱敏
程序猿大帅1 小时前
记一次线上翻车:加了Redisson分布式锁,数据还是被并发打穿了
后端
weixin_704266051 小时前
项目总结一
java·前端·spring boot·后端·spring
JimmtButler1 小时前
一台电脑,两个 Git 身份:公司 GitLab + 个人 GitHub 共存
后端