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!