Java

Difference between Interceptor and Filter in Spring MVC

27 September 2026 · 7 min read

Difference between Interceptor and Filter in Spring MVC

Building robust and efficient web applications with Spring MVC often involves intricate request processing. As developers, we constantly seek ways to enhance security, log requests, or modify responses before they reach the client. Spring MVC provides powerful mechanisms for this: Filters and Interceptors. While both serve to intercept requests and responses, their scope, capabilities, and positioning within the application lifecycle differ significantly. Understanding the subtle yet crucial difference between Interceptor and Filter in Spring MVC is key to making informed architectural decisions and leveraging each tool effectively. This article will demystify these components, helping you choose the right one for your specific needs, whether it’s for authentication, logging, or performance monitoring.

Understanding Servlet Filters: The Gateway to Your Application

Servlet Filters are fundamental components of the Java Servlet API, operating at the very beginning of the request processing chain, even before the request reaches any Spring MVC components. They reside within the Servlet container (like Tomcat or Jetty) and are managed by it. A filter’s primary role is to intercept incoming requests and outgoing responses, allowing you to preprocess or post-process them, independent of the specific web framework being used.

When a web request hits your application, it first passes through any configured Servlet Filters. These filters can perform various tasks such as authentication, authorization, logging, character encoding, data compression, and even URL rewriting. Because they operate at the Servlet container level, they don’t have direct access to Spring’s application context or its sophisticated features like handler methods or model attributes. They primarily interact with the HttpServletRequest and HttpServletResponse objects.

The lifecycle of a Servlet Filter involves three main methods: init(), doFilter(), and destroy(). The init() method is called once when the filter is initialized, allowing for setup tasks. The doFilter() method is the core of the filter, executed for every request that matches its URL pattern. Here, you can perform your processing, and critically, you must call chain.doFilter(request, response) to pass the request down the chain to the next filter or the target resource (e.g., Spring’s DispatcherServlet). Finally, destroy() is called when the filter is taken out of service, allowing for cleanup.

Exploring Spring MVC Interceptors: Inside the DispatcherServlet ---------------------------------------------------------------

Spring MVC Interceptors, on the other hand, are a core feature of the Spring web framework, operating within the DispatcherServlet’s request processing lifecycle. This means that by the time a request reaches an Interceptor, it has already passed through all Servlet Filters and the DispatcherServlet has initiated its processing. Interceptors provide a more granular level of control, specifically over the execution of handler methods (controller methods).

Interceptors are particularly useful for tasks that require access to the Spring application context, handler objects, or the ModelAndView object. Common use cases include logging method execution times, adding common data to the model for all views, checking user permissions before executing a specific controller method, or manipulating the response after the controller has generated it but before it’s rendered. They offer a powerful way to implement cross-cutting concerns in an aspect-oriented manner within your Spring MVC application.

A Spring MVC Interceptor implements the HandlerInterceptor interface, which defines three methods:

  1. preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): Called before the actual handler (controller method) is executed. Returns true to proceed with the execution chain, or false to stop it.
  2. postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): Called after the handler has executed, but before the view is rendered. This method has access to the ModelAndView object, allowing you to modify it.
  3. afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): Called after the complete request has finished, including view rendering. Useful for resource cleanup, even if an exception occurred.

This three-phase approach gives you fine-grained control at different stages of the Spring MVC request processing lifecycle. Key Distinctions: Filter vs. Interceptor in Spring MVC

The primary difference between Interceptor and Filter in Spring MVC lies in their scope, execution point, and access to application resources. Filters operate at the Servlet container level, acting as a gatekeeper for all requests entering your web application, irrespective of the framework. They are executed before Spring’s DispatcherServlet even gets a chance to process the request, making them suitable for concerns that apply broadly across the entire application, like character encoding or security checks that don’t depend on Spring’s context.

Interceptors, conversely, are an integral part of the Spring MVC framework and operate within the DispatcherServlet’s processing. This means they are invoked after the DispatcherServlet has received the request, determined the appropriate handler, but before the handler method executes, and also after the handler executes. This positioning grants Interceptors access to the handler object (the controller method) and the ModelAndView object, which is invaluable for tasks closely tied to the Spring MVC lifecycle, such as adding data to the model for all views or logging specific controller method invocations. Therefore, if your task requires knowledge of Spring’s internal workings or access to its beans, an Interceptor is the more appropriate choice.

To summarize the core distinctions:

  • Location/Scope: Filters are part of the Servlet container specification (jakarta.servlet.Filter) and operate outside the Spring context. Interceptors are part of the Spring Framework (org.springframework.web.servlet.HandlerInterceptor) and operate within the DispatcherServlet.
  • Execution Order: Filters execute first, before the DispatcherServlet. Interceptors execute after the DispatcherServlet has mapped the request to a handler, but before and after the handler’s execution.
  • Access to Spring Context: Interceptors have full access to the Spring application context, including beans, handler objects, and ModelAndView. Filters only have access to HttpServletRequest and HttpServletResponse objects.
  • Error Handling: Filters can catch exceptions thrown by resources down the chain. Interceptors’ afterCompletion method is specifically designed to handle cleanup after an exception has occurred, making them robust for error scenarios within the Spring MVC flow.

When to Use Which? Practical Scenarios and Best Practices

Choosing between a Servlet Filter and a Spring MVC Interceptor depends heavily on the nature and scope of the cross-cutting concern you’re addressing. Making the correct choice ensures optimal performance and maintainability of your application. Consider the following guidelines:

Use a Servlet Filter when:

  • The concern applies to all requests, regardless of which framework handles them.

  • You need to perform tasks that are independent of Spring’s application context, such as character encoding, compression, or global security Question & Answer :
    I’m a little bit confused about Filter and Interceptor purposes.

    As I understood from docs, Interceptor is run between requests. On the other hand Filter is run before rendering view, but after Controller rendered response.

    So where is the difference between postHandle() in Interceptor and doFilter() in Filter?

    Spring MVC sheme What is the best practise in which use cases it should be used? In this picture where works Filters and Interceptors?

    From HandlerIntercepter’s javadoc:

    HandlerInterceptor is basically similar to a Servlet Filter, but in contrast to the latter it just allows custom pre-processing with the option of prohibiting the execution of the handler itself, and custom post-processing. Filters are more powerful, for example they allow for exchanging the request and response objects that are handed down the chain. Note that a filter gets configured in web.xml, a HandlerInterceptor in the application context.

    As a basic guideline, fine-grained handler-related pre-processing tasks are candidates for HandlerInterceptor implementations, especially factored-out common handler code and authorization checks. On the other hand, a Filter is well-suited for request content and view content handling, like multipart forms and GZIP compression. This typically shows when one needs to map the filter to certain content types (e.g. images), or to all requests.

    With that being said:

    So where is the difference between Interceptor#postHandle() and Filter#doFilter()?

    postHandle will be called after handler method invocation but before the view being rendered. So, you can add more model objects to the view but you can not change the HttpServletResponse since it’s already committed.

    doFilter is much more versatile than the postHandle. You can change the request or response and pass it to the chain or even block the request processing.

    Also, in preHandle and postHandle methods, you have access to the HandlerMethod that processed the request. So, you can add pre/post-processing logic based on the handler itself. For example, you can add a logic for handler methods that have some annotations.

    What is the best practise in which use cases it should be used?

    As the doc said, fine-grained handler-related pre-processing tasks are candidates for HandlerInterceptor implementations, especially factored-out common handler code and authorization checks. On the other hand, a Filter is well-suited for request content and view content handling, like multipart forms and GZIP compression. This typically shows when one needs to map the filter to certain content types (e.g. images), or to all requests.