Open In App

Spring Boot – Interceptor

Spring Boot Interceptor is an additional component that will intercept every request and response dispatch and perform some operations on it.

Interceptors in web applications play a major in performing initial or finalization work.



Interceptors have one primary purpose – “To intercept an incoming or outgoing request”.

This intercepting behavior is done to perform some operation BEFORE or AFTER an action invocation. You can think of an interceptor as a mediator between the request and the business logic reserved for that request. Interceptor in Spring Boot can be implemented either by extending the HandlerInterceptorAdapter class or by implementing HandlerInterceptor Interface.



Interceptors are useful for many purposes some of which are listed below :

1. Logging

Logging is a common practice to understand the flow of code & debugging. Interceptors are widely for the same, Documenting or recording the requests made by the client or the responses sent back to them is generally useful in debugging and monitoring purposes.

2. Authentication

Authentication is a security mechanism that can be implemented inside an Interceptor before the request even reaches its appropriate controller. It can be intercepted by the Interceptor & authentication can be verified, if denied then the request doesn’t get delegated to the controller which not only minimizes the code but reduces a great overhead.

3. Request/Response Modification

Interceptors are also used for modifying requests & responses. It can be done in the following ways :

Limitations

Advantages

  1. Reusability: The interceptors we implement in our application, can be reused back & forth for handling a request & response to multiple requests. They also help us minimize the code in the controller, shifting the authentication, and modification logic from the controller to the Interceptor.
  2. Logging & Monitoring: Interceptors help us log, debug & monitor incoming & outgoing requests. This saves time, to apprehend the state of request back and forth.
  3. Security and Authentication: Interceptors can verify the request made & delegate it as per the verification.
  4. Easy Configuration: Interceptors can be easily configured without affecting the whole application as the primary purpose of the interceptor is just to intercept requests & responses.

Step-by-Step Implementation

Here’s a step-by-step implementation for implementing an Interceptor in Spring Boot.

  1. Spring Boot Version: 3.1.5
  2. Java version: 17

Spring boot starter file

Download the zip file and extract it wherever you want.

Directory Structure

Now we’re done with our setup and we can start implementing our Request Interceptor. Step one of the following 3 steps is completed :

1. POM File

We have included the following dependencies in our POM File:

Note: Lombok Library is completely OPTIONAL, you can write your own setters & getters. We’re using it for simplicity.




<?xml version="1.0" encoding="UTF-8"?>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.GeeksForGeeks</groupId>
    <artifactId>requestInterceptor</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>requestInterceptor</name>
    <description>Request Interceptor Demo</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
  
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
  
</project>

2. Entity Class

Below is our entity class, it contains 2 annotations:-




import lombok.AllArgsConstructor;
import lombok.Data;
  
@Data
@AllArgsConstructor
//* Student POJO to store data
public class Student {
    int id;
    String firstName;
    String lastName;
}

3. Configuration Class

This is a Java class annotated with @Configuration for auto-configuration that is, it indicates this class contains configuration for the spring application context. Basically, it indicates that this class will contain some beans that must be registered with the application context to be used in the application.

In summary, the whole point of creating a configured class is to register custom interceptors with the ‘InterceptorRegistry‘.




package com.GeeksforGeeks.requestinterceptorexample.config;
  
import com.GeeksforGeeks.requestinterceptorexample.RequestInterceptor.RequestInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  
@Configuration
public class RequestInterceptorConfig implements WebMvcConfigurer {
     
      // Register an interceptor with the registry, Interceptor name : RequestInterceptor
      @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestInterceptor());
    }
    //* We can register any number of interceptors with our spring application context
}

4. Request Interceptor

Request Interceptor is an additional component class that intercepts all the incoming and outgoing requests (before any action is performed). It has the following 3 methods :

1. preHandle(): When an interceptor is implemented, any request before reaching the desired controller will be intercepted by this interceptor and some pre-processing can be performed like logging, authentication, redirection, etc.

2. postHandle(): This method is executed after the request is served but just before the response is sent back to the client. It intercepts the request in the final stage, giving us a chance to make any final trivial adjustments.

3. afterCompletion(): This method is executed after the request and response mechanism is completed.

@Component annotation tells the component scanning mechanism that this class should be registered for component scanning.




import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
  
@Component
public class RequestInterceptor implements HandlerInterceptor {
  
    // Request is intercepted by this method before reaching the Controller
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  
        //* Business logic just when the request is received and intercepted by this interceptor before reaching the controller
        try {
            System.out.println("1 - preHandle() : Before sending request to the Controller");
            System.out.println("Method Type: " + request.getMethod());
            System.out.println("Request URL: " + request.getRequestURI());
        }
        //* If the Exception is caught, this method will return false
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
  
    // Response is intercepted by this method before reaching the client
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //* Business logic just before the response reaches the client and the request is served
        try {
            System.out.println("2 - postHandle() : After the Controller serves the request (before returning back response to the client)");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
  
    // This method is called after request & response HTTP communication is done.
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //* Business logic after request and response is Completed
        try {
            System.out.println("3 - afterCompletion() : After the request and Response is completed");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. REST Controller

The rest controller is to handle the requests, defining the endpoints – REST APIs to handle the requests. We’ve taken only a GET mapping for the simplicity of this example.

Code




import com.GeeksForGeeks.requestInterceptor.Entity.Student;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
  
import java.util.ArrayList;
import java.util.List;
  
@RestController
@RequestMapping("/api")
public class RESTController {
      
      // Return a list of students
    @GetMapping("/students")
    public List<Student> getStudents(){
          // Add Data to POJO    
        Student student1 = new Student(1,"Adwitiya", "Mourya");
        Student student2 = new Student(2,"David", "Goggins");
        Student student3 = new Student(3,"Andrew", "Huberman");
          
        // Create a new List
          List<Student> myList = new ArrayList<Student>();
        
        // Add Data to the list
          myList.add(student1);
        myList.add(student2);
        myList.add(student3);
        
        return myList;
    }
}

6. SpringBootApplication

Execute the following SpringBootApplication code:




package com.GeeksforGeeks.requestinterceptorexample;
  
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
  
@SpringBootApplication
public class RequestInterceptorExampleApplication {
  
    public static void main(String[] args) {
        SpringApplication.run(RequestInterceptorExampleApplication.class, args);
    }
}

Step-1: Test the response on Postman or any browser by going to – “default port/api/students”

Output window of testing REST API using PostMan

PostMan Output

Step-2: Check the console for preHandle, postHandle, and afterCompletion Method Outputs:

Console output of the interceptor methods

Console Output


Article Tags :