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,这样可以避免潜在的重复处理问题,提升应用的稳定性。

相关推荐
captain3767 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
IT_陈寒9 小时前
Java序列化踩坑记:对象循环引用让我加班两小时
前端·人工智能·后端
泡海椒9 小时前
05-雷达图多维画像-信用评级多维画像
后端
王中阳Go9 小时前
5.27 分钟干完后端和全部测试:一场三小时笔试的五个失分点,四个不在代码上
大数据·数据库·人工智能·后端·大语言模型
大哥43099 小时前
Modbus 的"字序":一个配错就变成天文数字,或者干脆变成 0
后端
岩钧9 小时前
New API 源码解析:一个生产级 AI 网关的架构与实现
后端
学到老活到老9 小时前
第 24 集:配置文件写了 80,Spring Boot 为什么读到 90?
java·后端·spring
用户360055579009 小时前
Kestrel_VLLM - 25 · 全注意力层设备化、整层对拍与访存粒度
后端
yliucherish9 小时前
从零实现一个 SQL 注入检测引擎:报错注入与布尔盲注的误报控制
后端
bigbread9 小时前
状态模式-住院患者状态管理
后端