org.springframework.web.filter

## Class OncePerRequestFilter

- java.lang.Object
- - org.springframework.web.filter.GenericFilterBean
  - - org.springframework.web.filter.OncePerRequestFilter

- All Implemented Interfaces:
    Filter, Aware, BeanNameAware, DisposableBean, InitializingBean, EnvironmentAware, ServletContextAware
  Direct Known Subclasses:
    AbstractRequestLoggingFilter, CharacterEncodingFilter, HiddenHttpMethodFilter, HttpPutFormContentFilter, MultipartFilter, OpenEntityManagerInViewFilter, OpenPersistenceManagerInViewFilter, OpenSessionInViewFilter, OpenSessionInViewFilter, RequestContextFilter, ShallowEtagHeaderFilter

      public abstract class OncePerRequestFilter
      extends GenericFilterBean

  Filter base class that aims to guarantee a single execution per request dispatch, on any servlet container. It provides a `doFilterInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)` method with HttpServletRequest and HttpServletResponse arguments.

  As of Servlet 3.0, a filter may be invoked as part of a `REQUEST` or `ASYNC` dispatches that occur in separate threads. A filter can be configured in `web.xml` whether it should be involved in async dispatches. However, in some cases servlet containers assume different default configuration. Therefore sub-classes can override the method `shouldNotFilterAsyncDispatch()` to declare statically if they shouuld indeed be invoked, once, during both types of dispatches in order to provide thread initialization, logging, security, and so on. This mechanism complements and does not replace the need to configure a filter in `web.xml` with dispatcher types.

  Sub-classes may use `isAsyncDispatch(HttpServletRequest)` to determine when a filter is invoked as part of an async dispatch, and use `isAsyncStarted(HttpServletRequest)` to determine when the request has been placed in async mode and therefore the current dispatch won't be the last one.

  Yet another dispatch type that also occurs in its own thread is `ERROR`. Sub-classes can override `shouldNotFilterErrorDispatch()` if they wish to declare statically if they should be invoked once during error dispatches.

  The `getAlreadyFilteredAttributeName()` method determines how to identify that a request is already filtered. The default implementation is based on the configured name of the concrete filter instance.

  Since:
    06.12.2003
  Author:
    Juergen Hoeller, Rossen Stoyanchev

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static String` | `ALREADY_FILTERED_SUFFIX` Suffix that gets appended to the filter name for the "already filtered" request attribute.

    - ### Fields inherited from class org.springframework.web.filter.GenericFilterBean

      `logger`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `OncePerRequestFilter()`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)` This `doFilter` implementation stores a request attribute for "already filtered", proceeding without filtering again if the attribute is already there.
    `protected abstract void` | `doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)` Same contract as for `doFilter`, but guaranteed to be just invoked once per request within a single request thread.
    `protected String` | `getAlreadyFilteredAttributeName()` Return the name of the request attribute that identifies that a request is already filtered.
    `protected boolean` | `isAsyncDispatch(HttpServletRequest request)` The dispatcher type `javax.servlet.DispatcherType.ASYNC` introduced in Servlet 3.0 means a filter can be invoked in more than one thread over the course of a single request.
    `protected boolean` | `isAsyncStarted(HttpServletRequest request)` Whether request processing is in asynchronous mode meaning that the response will not be committed after the current thread is exited.
    `protected boolean` | `shouldNotFilter(HttpServletRequest request)` Can be overridden in subclasses for custom filtering control, returning `true` to avoid filtering of the given request.
    `protected boolean` | `shouldNotFilterAsyncDispatch()` The dispatcher type `javax.servlet.DispatcherType.ASYNC` introduced in Servlet 3.0 means a filter can be invoked in more than one thread over the course of a single request.
    `protected boolean` | `shouldNotFilterErrorDispatch()` Whether to filter error dispatches such as when the servlet container processes and error mapped in `web.xml`.

    - ### Methods inherited from class org.springframework.web.filter.GenericFilterBean

      `addRequiredProperty, afterPropertiesSet, destroy, getFilterConfig, getFilterName, getServletContext, init, initBeanWrapper, initFilterBean, setBeanName, setEnvironment, setServletContext`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### ALREADY_FILTERED_SUFFIX

          public static final String ALREADY_FILTERED_SUFFIX

      Suffix that gets appended to the filter name for the "already filtered" request attribute.
      See Also:
        `getAlreadyFilteredAttributeName()`, Constant Field Values

  - ### Constructor Detail

    - #### OncePerRequestFilter

          public OncePerRequestFilter()

  - ### Method Detail

    - #### doFilter

          public final void doFilter(ServletRequest request,
                      ServletResponse response,
                      FilterChain filterChain)
                              throws ServletException,
                                     IOException

      This `doFilter` implementation stores a request attribute for "already filtered", proceeding without filtering again if the attribute is already there.
      Throws:
        `ServletException`
        `IOException`
      See Also:
        `getAlreadyFilteredAttributeName()`, `shouldNotFilter(javax.servlet.http.HttpServletRequest)`, `doFilterInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)`

    - #### isAsyncDispatch

          protected boolean isAsyncDispatch(HttpServletRequest request)

      The dispatcher type `javax.servlet.DispatcherType.ASYNC` introduced in Servlet 3.0 means a filter can be invoked in more than one thread over the course of a single request. This method returns `true` if the filter is currently executing within an asynchronous dispatch.
      Parameters:
        `request` - the current request
      See Also:
        `WebAsyncManager.hasConcurrentResult()`

    - #### isAsyncStarted

          protected boolean isAsyncStarted(HttpServletRequest request)

      Whether request processing is in asynchronous mode meaning that the response will not be committed after the current thread is exited.
      Parameters:
        `request` - the current request
      See Also:
        `WebAsyncManager.isConcurrentHandlingStarted()`

    - #### getAlreadyFilteredAttributeName

          protected String getAlreadyFilteredAttributeName()

      Return the name of the request attribute that identifies that a request is already filtered.

      Default implementation takes the configured name of the concrete filter instance and appends ".FILTERED". If the filter is not fully initialized, it falls back to its class name.

      See Also:
        `GenericFilterBean.getFilterName()`, `ALREADY_FILTERED_SUFFIX`

    - #### shouldNotFilter

          protected boolean shouldNotFilter(HttpServletRequest request)
                                     throws ServletException

      Can be overridden in subclasses for custom filtering control, returning `true` to avoid filtering of the given request.

      The default implementation always returns `false`.

      Parameters:
        `request` - current HTTP request
      Returns:
        whether the given request should not be filtered
      Throws:
        `ServletException` - in case of errors

    - #### shouldNotFilterAsyncDispatch

          protected boolean shouldNotFilterAsyncDispatch()

      The dispatcher type `javax.servlet.DispatcherType.ASYNC` introduced in Servlet 3.0 means a filter can be invoked in more than one thread over the course of a single request. Some filters only need to filter the initial thread (e.g. request wrapping) while others may need to be invoked at least once in each additional thread for example for setting up thread locals or to perform final processing at the very end.

      Note that although a filter can be mapped to handle specific dispatcher types via `web.xml` or in Java through the `ServletContext`, servlet containers may enforce different defaults with regards to dispatcher types. This flag enforces the design intent of the filter.

      The default return value is "true", which means the filter will not be invoked during subsequent async dispatches. If "false", the filter will be invoked during async dispatches with the same guarantees of being invoked only once during a request within a single thread.

    - #### shouldNotFilterErrorDispatch

          protected boolean shouldNotFilterErrorDispatch()

      Whether to filter error dispatches such as when the servlet container processes and error mapped in `web.xml`. The default return value is "true", which means the filter will not be invoked in case of an error dispatch.

    - #### doFilterInternal

          protected abstract void doFilterInternal(HttpServletRequest request,
                              HttpServletResponse response,
                              FilterChain filterChain)
                                            throws ServletException,
                                                   IOException

      Same contract as for `doFilter`, but guaranteed to be just invoked once per request within a single request thread. See `shouldNotFilterAsyncDispatch()` for details.

      Provides HttpServletRequest and HttpServletResponse arguments instead of the default ServletRequest and ServletResponse ones.

      Throws:
        `ServletException`
        `IOException`