Interceptors in SpringBoot with Example – HandlerInterceptor:

What is an Interceptor?

Interceptors are used to intercept the requests and process them before sending it to the controller. It can be used for logging before sending requests to controller, add attributes, authorization etc. We can also have any number of interceptors for the application.

Seems similar to filters? so what is the difference between them?

There are differences between Filters and Interceptors,

  • Filters are configured in web.xml where as HandlerInterceptor in Application Context.
  • HandlerInterceptor: is basically similar to a Servlet 2.3 Filter, but in contrast to the latter it just allows custom pre-processing with the option of prohibiting the execution of the handler itself, and custom post-processing
  • Filters: are more powerful, for example they allow for exchanging the request and response objects that are handed down the chain

Reference java docs.

What is a Handler Interceptor?

HandlerInterceptor is an interface which allows for customized handler execution chains. A HandlerInterceptor gets called before the appropriate HandlerAdapter triggers the execution of the handler itself.

There are 3 methods in HandlerInterceptor interface,

    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }

Let us discuss these methods in detail,

default boolean preHandle:

This method is called before the execution of the handler, that is called after determining the appropriate handler object but before invoking them.

This method can throw an exception if any error occurs.

The default value is true.

default void postHandle:

This method will get executed after successful execution of the handler. This method is called when HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view.

The default value is empty

default void afterCompletion:

This method will be called after rendering the view. This allows for a proper resource clean up.

The default value is empty.

Now let us see an example,

project structure

First lets create our custom interceptor and override the methods,

Creating Interceptor:

package com.javainfinite.interceptor.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class CustomInterceptor implements HandlerInterceptor {

    Logger logger = LoggerFactory.getLogger(CustomInterceptor.class);

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("Method in Pre handle");
        request.setAttribute("Interceptor", "InterceptorAttribute");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           @Nullable ModelAndView modelAndView) throws Exception {
        logger.info("Method in postHandle");
        response.setStatus(200);
    }


    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                @Nullable Exception ex) throws Exception {
        logger.info("Method in after Completion with Request: "+request+" Response: "+response);

    }
}

We have overridden the three methods – PreHandle, PostHandle and AfterCompletion. preHandle will be called before calling the handler, postHandle will be called after the handler completes its execution and afterCompletion will be called after the return statement.

We have set couple of attributes, First we have set an attribute before the handler method is called. Second, we have set an attribute after the handler method is called.

Now we need to register our Interceptor,

Registering Interceptor:

package com.javainfinite.interceptor.configuration;

import com.javainfinite.interceptor.interceptor.CustomInterceptor;
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 InterceptorConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/**");
    }
}

We have included the interceptors are all the URL patterns (“/**”). We can create multiple interceptors for specific calls too. But in this example for our understanding let us use a simple interceptor.

Controller:

package com.javainfinite.interceptor.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
public class InterceptorController {

    Logger logger = LoggerFactory.getLogger(InterceptorController.class);

    @GetMapping("/interceptor")
    public String homepage(ModelMap model, HttpServletRequest request, HttpServletResponse response) {
        logger.info("Controller method invoked");
        model.addAttribute("Interceptor", request.getAttribute("Interceptor"));
        model.addAttribute("Status", response.getStatus());
        return "hello " + request.getAttribute("Interceptor") + " " + response.getStatus();
    }
}

Main Application:

package com.javainfinite.interceptor;

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

@SpringBootApplication
public class InterceptorApplication {

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

}

Let us see the output,

output

Our attributes which we have added in interceptors are fetched and displayed.

Now let us see the console for logs,

From the output we can see

preHandle called before the handler is invoked and postHandle is called after handler is invoked and finally afterCompletion is called after the handler process is completed.Thats it about the basic level of interceptors.

Code is available for download here.

By Sri

Leave a Reply

Your email address will not be published. Required fields are marked *