Spring 过滤器:OncePerRequestFilter 应用详解

在Web应用中,过滤器(Filter)是一个强大的工具,它可以在请求到达目标资源之前或响应返回客户端之前对请求或响应进行拦截和处理。然而,在某些情况下,我们可能希望确保过滤器逻辑在一次完整的HTTP请求中仅执行一次,即使请求在服务器内部经过了多次转发(forward)或包含多个资源请求。Spring框架的OncePerRequestFilter就是为了满足这一需求而设计的。

一、OncePerRequestFilter 概述

OncePerRequestFilter是Spring提供的一个过滤器基类,它确保了在一次完整的HTTP请求中,无论请求经过多少次内部转发,过滤器的逻辑都只会被执行一次。这对于需要在请求处理之前或之后进行一次性设置或清理资源的场景特别有用。

二、OncePerRequestFilter 的原理

OncePerRequestFilter通过内部使用HttpServletRequest的getAttribute和setAttribute方法,以及一个ThreadLocal变量来跟踪当前请求是否已经被处理过。当请求首次进入过滤器时,OncePerRequestFilter会检查是否已经存在一个与当前请求关联的标记。如果不存在,则执行过滤器的逻辑,并将一个标记与当前请求关联起来;如果已经存在,则直接跳过过滤器的逻辑。

三、OncePerRequestFilter 的使用

要使用OncePerRequestFilter,你需要创建一个类并继承它,然后重写doFilterInternal方法。doFilterInternal方法是实际执行过滤器逻辑的地方。

下面是一个简单的示例,展示了一个自定义的OncePerRequestFilter,它在请求到达目标资源之前记录请求的开始时间,并在响应返回客户端之前记录请求的处理时间:

复制代码
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");  
    }  
}

四、注册 OncePerRequestFilter

要将自定义的OncePerRequestFilter注册到Spring应用中,你可以使用Java配置或XML配置。在Java配置中,你可以创建一个FilterRegistrationBean的Bean来注册你的过滤器:

复制代码
import org.springframework.boot.web.servlet.FilterRegistrationBean;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
  
@Configuration  
public class FilterConfig {  
  
    @Bean  
    public FilterRegistrationBean<TimingFilter> timingFilterRegistration() {  
        FilterRegistrationBean<TimingFilter> registration = new FilterRegistrationBean<>();  
        registration.setFilter(new TimingFilter());  
        registration.addUrlPatterns("/*"); // 设置过滤器拦截的URL模式  
        return registration;  
    }  
}

五、总结

OncePerRequestFilter是Spring框架中一个非常有用的工具,它可以帮助你在一次完整的HTTP请求中仅执行一次过滤器的逻辑。通过继承OncePerRequestFilter并重写doFilterInternal方法,你可以轻松地创建自定义的过滤器来处理各种需求。无论是在记录请求处理时间、设置请求属性、进行权限验证等方面,OncePerRequestFilter都能为你提供强大的支持。

参考文献:

相关推荐
小码哥_常6 分钟前
Spring Boot 实现网络限速:让流量“收放自如”
后端
东离与糖宝10 分钟前
Java 26+Spring Boot 3.5,微服务启动从3秒压到0.8秒
java·人工智能
禹中一只鱼31 分钟前
【力扣热题100学习笔记】 - 哈希
java·学习·leetcode·哈希算法
凌波粒32 分钟前
LeetCode--349.两个数组的交集(哈希表)
java·算法·leetcode·散列表
于先生吖40 分钟前
Java+SpringBoot 无人健身房物联网系统完整源码实现
java·spring boot·物联网
johnrui1 小时前
SpringBoot-JdbcTemplate
java·spring boot·后端
码云社区1 小时前
JAVA二手车交易二手车市场系统源码支持微信小程序+微信公众号+H5+APP
java·开发语言·微信小程序·二手交易·闲置回收
crescent_悦1 小时前
C++:The Largest Generation
java·开发语言·c++
indexsunny1 小时前
互联网大厂Java面试实战:从Spring Boot到微服务的技术问答解析
java·spring boot·redis·微服务·消息队列·电商
Victor3562 小时前
MongoDB(72)如何创建用户和角色?
后端