Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Spring Boot Interceptors: Implementation and Source Code Analysis

Tech May 8 3

This article delves into the implementation and underlying source code of Spring Boot interceptors, examining their role in request processing. We'll explore how to configure and utilize them, and trace their execution flow from request reception to response generation.

Configuring Interceptors

To implement an interceptor in Spring Boot, you typically create a configuration class that implements the WebMvcConfigurer interface. This interface provides a method, addInterceptors, where you can register your custom interceptor instances.


@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyCustomInterceptor());
    }
}

Custom Interceptor Example

A custom interceptor can extend HandlerInterceptorAdapter or implement the HandlerInterceptor interface directly. It provides methods like preHandle, postHandle, and afterCompletion that are invoked at different stages of the request processing lifecycle.


/**
 * A sample custom interceptor.
 */
public class MyCustomInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Executing preHandle method...");
        // Return true to continue processing, false to halt the request.
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Executing postHandle method...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Executing afterCompletion method...");
        // This method is always called, even if an exception occurs.
        // For demonstration, we'll simulate an exception here.
        // if (ex == null) {
        //     System.out.println("Request completed successfully.");
        // } else {
        //     System.out.println("Request completed with an exception: " + ex.getMessage());
        // }
    }
}

Interceptor Lifecycle and Spring Boot Bootstrapping

During Spring Boot startup, specifically within the doCreateBean phase, Spring Boot's auto-configuration (WebMvcAutoConfiguration) identifies and registers all classes implementing WebMvcConfigurer. Your custom configuration class, WebConfiguration, is among these, ensuring your interceptor is added to the framework's interceptor list.

Request Processing Flow

When a client request arrives, it follows a specific path:

  1. Tomcat Container: The request is first received by the embedded Tomcat server.
  2. DispatcherServlet: The request is then handed over to the DispatcherServlet, the central handler in Spring MVC.
  3. Filters: Before reaching Spring's interceptors, the request passes through Servlet filters. If a filter chain is not properly processed, the request might be halted here, preventing interceptor invocation. The creation of the filter chain involves mechanisms like ApplicationFilterFactory.createFilterChain.
  4. Interceptors: Once the request successfully passes through all configured filters, it proceeds to the Spring MVC interceptor chain.

Invoking Interceptors via DispatcherServlet

The DispatcherServlet's doDispatch method orchestrates the request handling, including interceptor calls. Here's a breakdown of key parts:

  • getHandler(processedRequest): Determines the appropriate handler (controller method) for the incoming request.
  • applyPreHandle(processedRequest, response): This method iterates through all registered interceptors and calls their preHandle methods. If any preHandle method returns false, request processing stops, and the interceptor chain is not further invoked. The triggerAfterCompletion method is called evenif preHandle fails.
  • ha.handle(...): If all preHandle methods return true, the actual handler method is invoked.
  • applyPostHandle(...): After the handler method has executed (but before the view is rendered), the postHandle methods of the interceptors are called in reverse order.
  • processDispatchResult(...): This method manages the outcome of the dispatch process.
  • triggerAfterCompletion(...): Regardless of whether the request processing succeeded or threw an exception, the afterCompletion methods of the interceptors are called. This is crucial for cleanup tasks. The source code for triggerAfterCompletion shows it iterates through interceptors and calls their afterCompletion method, handling potential exceptions gracefully to avoid disrupting the overall request flow.

The afterCompletion method is designed to be resilient; any exceptions thrown within it are caught and logged, but they do not prevent the final response from being sent back to the client.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.