Java
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.
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:
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): Called before the actual handler (controller method) is executed. Returnstrueto proceed with the execution chain, orfalseto stop it.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 theModelAndViewobject, allowing you to modify it.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 theDispatcherServlet. - Execution Order: Filters execute first, before the
DispatcherServlet. Interceptors execute after theDispatcherServlethas 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 toHttpServletRequestandHttpServletResponseobjects. - Error Handling: Filters can catch exceptions thrown by resources down the chain. Interceptors’
afterCompletionmethod 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 aboutFilterandInterceptorpurposes.As I understood from docs,
Interceptoris run between requests. On the other handFilteris run before rendering view, but after Controller rendered response.So where is the difference between
postHandle()in Interceptor anddoFilter()in Filter?
What is the best practise in which use cases it should be used? In this picture where works Filters andInterceptors?From
HandlerIntercepter’s javadoc:HandlerInterceptoris basically similar to a ServletFilter, 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 inweb.xml, aHandlerInterceptorin the application context.As a basic guideline, fine-grained handler-related pre-processing tasks are candidates for
HandlerInterceptorimplementations, especially factored-out common handler code and authorization checks. On the other hand, aFilteris 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()andFilter#doFilter()?postHandlewill 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 theHttpServletResponsesince it’s already committed.doFilteris much more versatile than thepostHandle. You can change the request or response and pass it to the chain or even block the request processing.Also, in
preHandleandpostHandlemethods, you have access to theHandlerMethodthat 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
HandlerInterceptorimplementations, especially factored-out common handler code and authorization checks. On the other hand, aFilteris 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.