Mastering Interceptors in Java and Spring Boot — Trusting the Right Code
When working with web applications, there are times when you need to perform operations before or after the actual handling of a request by your controller. Interceptors allow you to accomplish this efficiently in a non-intrusive manner. In this blog, we will explore how to use interceptors in Java and Spring Boot, and how they help enhance the behaviour of your application.
What Are Interceptors?
Interceptors are a powerful mechanism in web applications that enable you to intercept and modify the processing of requests and responses. They are often used for cross-cutting concerns like logging, authentication, authorization, and request validation.
In Spring Boot, interceptors are a part of the HandlerInterceptor interface in the Spring Web MVC framework. They allow you to inspect, transform, or log data at three main stages of request processing:
- Pre-Handle: Before the request reaches the controller.
- Post-Handle: After the request has been processed by the controller but before the response is returned.
- After Completion: After the complete request cycle is finished, useful for resource cleanup.
Use Cases of Interceptors
- Logging: You can log details about incoming requests, such as the URL, HTTP method, and headers.
- Authentication & Authorization: You can intercept a request to check if a user is authenticated or authorised to access a specific resource.
- Request Validation: Pre-handle the request to validate data before passing it to the controller.
- Performance Monitoring: Measure the time taken to handle requests by intercepting at the start and end.
- Data Transformation: Modify the incoming request data or outgoing response data.
How to Implement Interceptors in Spring Boot
Let’s dive into the steps to create and register an interceptor in Spring Boot.
1. Implementing HandlerInterceptor
First, create a class that implements the HandlerInterceptor interface. You need to override at least one of its three methods:
- preHandle()
- postHandle()
- afterCompletion()
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class CustomInterceptor implements HandlerInterceptor {
// Pre-handle: before the request reaches the controller
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Pre Handle method is Calling - URL: " + request.getRequestURL());
// Return true to proceed to the next interceptor/controller
return true;
}
// Post-handle: after the controller processes the request
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
System.out.println("Post Handle method is Calling");
}
// After completion: after the complete request has finished
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception {
System.out.println("Request and Response is completed");
}
}
2. Registering the Interceptor
Once the interceptor is defined, you need to register it within the Spring context. This can be done by implementing the WebMvcConfigurer interface.
import org.springframework.beans.factory.annotation.Autowired;
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 WebConfig implements WebMvcConfigurer {
@Autowired
private CustomInterceptor customInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor)
.addPathPatterns("/api/**") // Specify the URL patterns to intercept
.excludePathPatterns("/api/auth/**"); // Exclude specific URL patterns if needed
}
}
In this example, the CustomInterceptor is applied to all paths that match /api/**, except for /api/auth/**. You can customize the interceptor based on your needs.
3. Testing the Interceptor
Once you have implemented and registered the interceptor, you can start testing it. Every time you hit an API that matches the specified pattern, the preHandle(), postHandle(), and afterCompletion() methods of the interceptor will be executed.
Real-World Example: Using an Interceptor for Logging
Logging is one of the most common uses of interceptors. Let’s create an interceptor that logs the time taken for a request to be processed.
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.setAttribute("startTime", System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
System.out.println("[" + handler + "] executeTime : " + executionTime + "ms");
}
}
This interceptor calculates the execution time of each request and logs it to the console.
Trust Is an Expensive Thing — Be Careful About Who You Trust
“Trust is a very expensive thing. You can’t expect it from cheap people.” This saying holds true not only in life but also in software development. The authenticity of both code and people plays a crucial role in success.
Imagine you’re part of a development team building a complex application. You hire a freelance developer who offers to write key components at a fraction of the usual cost. Things seem to be going well, but when the critical deadline approaches, the code begins to fail. Testing reveals deep flaws: security vulnerabilities, poorly written logic, and hidden bugs that compromise the integrity of the entire system.
Why did this happen? The freelance developer promised quick, inexpensive results, but in reality, they cut corners and delivered subpar work. The result was costly — both in time and trust.
This kind of scenario happens not just in software but in all walks of life. You should always verify the authenticity and integrity of people and the work they deliver. Trust is something that should be earned, and you should always have mechanisms (just like interceptors in code) that allow you to check and verify authenticity before blindly trusting anyone.
Conclusion
Interceptors in Java and Spring Boot are a highly useful and flexible mechanism for addressing cross-cutting concerns such as logging, security, and performance monitoring. They enable you to define logic at key points in the request lifecycle without cluttering your controller code. Mastering the use of interceptors can greatly enhance the maintainability and efficiency of your Spring Boot applications.
Similarly, in life and work, trust should never be given blindly. Whether it’s people or code, always take the time to ensure the authenticity of who or what you are dealing with. Trust may be expensive, but it’s one of the most valuable assets you’ll ever have.
References:
- Spring Documentation on Interceptors
- Baeldung: Spring Handler Interceptor
- Gupta, Dinesh. “Logging in Spring MVC.” Java Code Geeks, May 2023.
- Johnson, Rod. “Spring Framework.” Spring Documentation, Version 5, January 2024.
- Craig Walls. Spring in Action. 6th ed., Manning Publications, 2022.
- Josh Long. “Spring Security and Interceptors.” Spring Security blog, February 2023.
- Rozner, Charles. “Best Practices for Spring Boot Interceptors.” Spring Blog, April 2024.
- Maxwell, John. The 21 Irrefutable Laws of Leadership. HarperCollins Leadership, 2020.