SoFunction
Updated on 2025-04-11

Implementation of OncePerRequestFilter application in Spring filter

In web applications, a filter is a powerful tool that intercepts and processes requests or responses before a request reaches the target resource or before a response returns to the client. However, in some cases, we may want to ensure that the filter logic is executed only once in a full HTTP request, even if the request has been forwarded multiple times inside the server or contains multiple resource requests. Spring framework's OncePerRequestFilter is designed to meet this need.

1. Overview of OncePerRequestFilter

OncePerRequestFilter is a filter base class provided by Spring. It ensures that in a full HTTP request, the filter logic will only be executed once no matter how many internal forwardings the request has been made. This is especially useful for scenarios where resources need to be set up or cleaned up at one time before or after request processing.

2. The principle of OncePerRequestFilter

OncePerRequestFilter uses the getAttribute and setAttribute methods of HttpServletRequest internally, as well as a ThreadLocal variable to track whether the current request has been processed. When the request first enters the filter, OncePerRequestFilter checks whether a tag associated with the current request already exists. If it does not exist, the logic of the filter is executed and a tag is associated with the current request; if it already exists, the logic of the filter is skipped directly.

3. Use of OncePerRequestFilter

To use OncePerRequestFilter, you need to create a class and inherit it, and then override the doFilterInternal method. The doFilterInternal method is where the filter logic is actually executed.

Here is a simple example showing a custom OncePerRequestFilter that records the start time of the request before the request reaches the target resource and the processing time of the request before the response returns to the client:

import ;  
import ;  
import ;  
import ;  
import ;  
import ;  
  
public class TimingFilter extends OncePerRequestFilter {  
  
    @Override  
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
            throws ServletException, IOException {  
          
        // Record the request start time        long startTime = ();  
          
        // Continue the filter chain        (request, response);  
          
        // Record the request processing time        long endTime = ();  
        long duration = endTime - startTime;  
        ("Request took " + duration + " ms to process");  
    }  
}

4. Register OncePerRequestFilter

To register a custom OncePerRequestFilter into your Spring application, you can use Java configuration or XML configuration. In Java configuration, you can create a FilterRegistrationBean bean to register your filter:

import ;  
import ;  
import ;  
  
@Configuration  
public class FilterConfig {  
  
    @Bean  
    public FilterRegistrationBean<TimingFilter> timingFilterRegistration() {  
        FilterRegistrationBean<TimingFilter> registration = new FilterRegistrationBean<>();  
        (new TimingFilter());  
        ("/*"); // Set the URL mode for filter intercept        return registration;  
    }  
}

5. Summary

OncePerRequestFilter is a very useful tool in the Spring framework that helps you execute the logic of filters only once in a full HTTP request. By inheriting the OncePerRequestFilter and overriding the doFilterInternal method, you can easily create custom filters to handle various needs. Whether it is recording request processing time, setting request attributes, performing permission verification, etc., OncePerRequestFilter can provide you with powerful support.

References:

  • /spring-onceperrequestfilter/

This is the article about the implementation of the OncePerRequestFilter application in Spring filters. For more related Spring OncePerRequestFilter content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!