Spring: HandlerInterceptor Example

In this section, we will learn about using Spring HandlerInterceptor in Spring Boot application.

The Spring framework includes HandlerInterceptors, which are positioned in between DispatcherServlet and our Controllers. The primary purpose of interceptor is to intercept incoming request and response. It perform some operations on request and response.

In Spring, an interceptor can be implemented by implementing HandlerInterceptor Interface.

There are numerous uses for interceptors, some of which are mentioned below:

1. Logging

Monitoring and troubleshooting running apps require logging. Using a combination of interceptors and Spring Boot's logging framework, we can log all requests, responses, and errors in a single location within an application.


2. Authentication & Authorization

Incoming request can be intercepted by the Interceptor & authentication or authorization can be done, if denied then the request does not get delegated to the controller.


3. Request Response Modification

  • Changing or adding parameters to a the incoming request.
  • Changing or adding response or request headers.
  • Changing http status code. 
  • and more...


4. Caching and More...


*Note: While using interceptors, we should consider the performance and security of the application on our own.

Spring HandlerInterceptor declares three methods based on where we want to intercept the HTTP request.

1. preHandle

  public boolean preHandle(HttpServletRequest request,
                         HttpServletResponse response,
Object handler) throws Exception{...}

Intercepting requests before they reach the Controller handler method. A handler method is a method in a controller class that processes HTTP requests.


2. postHandle

     public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {...}

Allows for the modification of model data or response headers by running after the controller handler method but before view rendering.


3. afterCompletion

    public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
Object handler, Exception ex) throws Exception {...}

This method that is called once the handler is executed and view is rendered. Regardless of the success or failure of the handler, always executes for resource management, logging, and cleanup tasks.


Complete example

First, open the Spring initializr https://start.spring.io

Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact spring-interceptors. Here I selected the Maven project - language Java 17 - Spring Boot 3.3.0, and Spring Web.

Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-interceptors) file and downloads the project. Then, Extract the Zip file. 

Then, import the project on your favourite IDE. 

Final Project Directory:


Complete pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-interceptors</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-interceptors</name>
<description>Demo project for Spring Boot</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.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>
</plugin>
</plugins>
</build>

</project>


Create TestController

Let’s create a controller class and a handler method for testing purpose.
package com.knf.dev.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

@GetMapping("/hello")
public String message() {
return "Hello";
}
}


Defining an interceptor

Let’s create MyInterceptor.
package com.knf.dev.demo.interceptor;

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 MyInterceptor implements HandlerInterceptor {

//Intercepting requests before they reach the Controller handler method
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
try {
System.out.println("Inside preHandle() : " +
"Before sending request to the Controller handler method");

} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}


/*
Allows for the modification of model data or response headers by
running after the controller handler method but before view rendering.
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
try {
System.out.println("Inside postHandle() : After the Controller " +
"serves the request and before returning back " +
"response to the client)");
} catch (Exception e) {
e.printStackTrace();
}
}

/*
This method that is called once the handler is executed and view is rendered.
Regardless of the success or failure of the handler, always executes for
resource management, logging, and cleanup tasks.
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) throws Exception {

try {
System.out.println("Inside afterCompletion() : " +
"After the request and Response is completed");
} catch (Exception e) {
e.printStackTrace();
}
}
}


Adding interceptor to a Registry

Let’s register an interceptor in order to make it available in Spring. We can register several interceptors in this manner.
package com.knf.dev.demo.config;

import com.knf.dev.demo.interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

// Register an interceptor with the registry
// Interceptor name : MyInterceptor
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
}


Run the application - SpringInterceptorsApplication.java

package com.knf.dev.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringInterceptorsApplication {

public static void main(String[] args) {
SpringApplication.run(SpringInterceptorsApplication.class, args);
}

}

Run the Spring Boot application - mvn spring-boot:run


OR 


Run this Spring boot application from 

  • IntelliJ IDEA IDE by right click - Run 'Application.main()' 
  • Eclipse/STS - You can right click the project or the Application.java file and run as java application or Spring boot application.

Test the endpoint on Postman or any browser.

Output window of testing REST API using Postman,

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

Source code - click here!

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete