Spring Boot Interceptor

Spring Boot Interceptors are useful tools for intercepting the HTTP request process. The concept is similar to AOP pointcuts and you can have them easily plugged and unplugged from the HTTP request process flow.

Basically, Interceptor is similar to a Servlet Filter, but in contrast to the latter, It is located after DispatcherServlet and as a result, related HandlerInterceptor class configured inside the application context. Filters are known to be more powerful, they are allowed to exchange the request and response objects that are handed down the chain whereas, Interceptors are just allowed to add some customer custom pre-processing, option of prohibiting the execution, and also custom post-processing. You can read about Spring Boot Filter in another post here.

HandlerInterceptor interface

HandlerInterceptor interface from org.springframework.web.servlet package is the interface that needed to be implemented in order to have an interceptor inside your Spring Boot application. This interface has 3 methods that will control the logic needed to be executed at different stages of processing the HTTP requests.

preHandle

This method will be called before sending the request to the controller. Returning false in this method will stop the process from passing the request to the controller

boolean preHandle(
javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
java.lang.Object handler)
throws java.lang.Exception

postHandle

This method will be used to perform operations before sending the response to the client.

void postHandle(
javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
java.lang.Object handler,
org.springframework.web.servlet.ModelAndView modelAndView)
throws java.lang.Exception

afterCompletion

This method will be used for operations after the whole cycle was completed and the view is generated

void afterCompletion(
javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
java.lang.Object handler,
java.lang.Exception ex)
throws java.lang.Exception

After having the interface implemented you need to register the implementation into InterceptorRegistry via addInterceptors method in WebMvcConfigurer.

Spring Boot Example

Imagine that you need to have the response time of the request logged in your application for performance evaluation and debugging purposes. HandlerInterceptor can help to set up this log for all or some of your endpoints simply.

HandlerInterceptor Implementation

In the following example, you will see how can we have an interceptor plugged into the application that can help to log the response time of the request.

@Slf4j
public class LogInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
UUID uuid = UUID.randomUUID();
request.setAttribute("start" , System.currentTimeMillis());
request.setAttribute("request-id", uuid );
log.info( "{} - calling {}" , uuid , request.getRequestURI() );
return true;
}

@Override
public void postHandle( HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
log.info( "{} - response in {}ms",
request.getAttribute("request-id"),
System.currentTimeMillis() - (long) request.getAttribute("start") );
}

@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception exception) throws Exception {
log.info( "{} - completed in {}ms",
request.getAttribute("request-id"),
System.currentTimeMillis() - (long) request.getAttribute("start") );
}
}

As you can see we have the LogInterceptor implementing the HandlerInterceptor and inside preHandle method we have set a unique id to trace the request and also start currentTimeMillis to calculate the response time. In postHandle we get these attributes from the request and log the response time and the unique id.

Adding to InterceptorRegistry

Now the next step is to add it to the InterceptorRegistry and test it.

@Configuration
public class WebConfig implements WebMvcConfigurer {

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

}

Adding the interceptor can be easily done by having the addInterceptors method inWebMvcConfigurer implemented and providing the required configuration.

registry.addInterceptor( new LogInterceptor() ).addPathPatterns("/student/**");

Using addPathPatterns you can limit the path that you want to apply this interceptor. After calling APIs you will get the following details in the log:

... 1dc2779c-d5e1-47e0-8faf-e9d7892c1089 - calling /student/1
... 1dc2779c-d5e1-47e0-8faf-e9d7892c1089 - response in 99ms
... 1dc2779c-d5e1-47e0-8faf-e9d7892c1089 - completed in 99ms

Interception order

Using the order method you can control the interception order like this:

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor( new LogInterceptor() ).order(1);
registry.addInterceptor( new AuthenticationInterceptor() ).order(2);
}

You can find the code for this project on Github.

Hope this article helped you and please support me with your applauding for the story. if you don’t know how it is just like this:

Or buy me a coffee here!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Farzin Pashaee

Farzin Pashaee

Software Engineer at Maybank, AI and ML enthusiastic