Tutorial

Spring MVC Interceptor HandlerInterceptorAdapter, HandlerInterceptor Example

Published on August 3, 2022
author

Pankaj

Spring MVC Interceptor HandlerInterceptorAdapter, HandlerInterceptor Example

Spring Interceptor are used to intercept client requests and process them. Sometimes we want to intercept the HTTP Request and do some processing before handing it over to the controller handler methods. That’s where Spring MVC Interceptor come handy.

Spring Interceptor

spring interceptor, spring mvc interceptor, HandlerInterceptorAdapter, HandlerInterceptor Just like we have Struts2 Interceptors, we can create our own Spring interceptor by either implementing org.springframework.web.servlet.HandlerInterceptor interface or by overriding abstract class org.springframework.web.servlet.handler.HandlerInterceptorAdapter that provides the base implementation of HandlerInterceptor interface.

Spring Interceptor - HandlerInterceptor

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

  1. boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): This method is used to intercept the request before it’s handed over to the handler method. This method should return ‘true’ to let Spring know to process the request through another spring interceptor or to send it to handler method if there are no further spring interceptors. If this method returns ‘false’ Spring framework assumes that request has been handled by the spring interceptor itself and no further processing is needed. We should use response object to send response to the client request in this case. Object handler is the chosen handler object to handle the request. This method can throw Exception also, in that case Spring MVC Exception Handling should be useful to send error page as response.
  2. void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): This HandlerInterceptor interceptor method is called when HandlerAdapter has invoked the handler but DispatcherServlet is yet to render the view. This method can be used to add additional attribute to the ModelAndView object to be used in the view pages. We can use this spring interceptor method to determine the time taken by handler method to process the client request.
  3. void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): This is a HandlerInterceptor callback method that is called once the handler is executed and view is rendered.

If there are multiple spring interceptors configured, preHandle() method is executed in the order of configuration whereas postHandle() and afterCompletion() methods are invoked in the reverse order. Let’s create a simple Spring MVC application where we will configure an Spring Interceptor to log timings of controller handler method. Our final Spring Interceptor example project will look like below image, we will look into the components that we are interested in. Spring MVC Interceptor, Spring Interceptor example, Spring interceptor

Spring Interceptor - Controller Class

package com.journaldev.spring;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! The client locale is {}.", locale);
		//adding some time lag to check interceptor execution
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		logger.info("Before returning view page");
		return "home";
	}
	
}

I am just adding some processing time in the execution of the handler method to check our spring interceptor methods in action.

Spring MVC Interceptor - HandlerInterceptorAdapter Implementation

For simplicity, I am extending abstract class HandlerInterceptorAdapter. HandlerInterceptorAdapter is abstract adapter class for the HandlerInterceptor interface, for simplified implementation of pre-only/post-only interceptors.

package com.journaldev.spring;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class RequestProcessingTimeInterceptor extends HandlerInterceptorAdapter {

	private static final Logger logger = LoggerFactory
			.getLogger(RequestProcessingTimeInterceptor.class);

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		long startTime = System.currentTimeMillis();
		logger.info("Request URL::" + request.getRequestURL().toString()
				+ ":: Start Time=" + System.currentTimeMillis());
		request.setAttribute("startTime", startTime);
		//if returned false, we need to make sure 'response' is sent
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("Request URL::" + request.getRequestURL().toString()
				+ " Sent to Handler :: Current Time=" + System.currentTimeMillis());
		//we can add attributes in the modelAndView and use that in the view page
	}

	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		long startTime = (Long) request.getAttribute("startTime");
		logger.info("Request URL::" + request.getRequestURL().toString()
				+ ":: End Time=" + System.currentTimeMillis());
		logger.info("Request URL::" + request.getRequestURL().toString()
				+ ":: Time Taken=" + (System.currentTimeMillis() - startTime));
	}

}

The logic is really simple, I am just logging the timings of handler method execution and total time taken in processing the request including rendering view page.

Spring MVC Interceptor Configuration

We have to wire the spring interceptor to the requests, we can use mvc:interceptors element to wire all the interceptors. We can also provide URI pattern to match before including the spring interceptor for the request through mapping element. Our final spring bean configuration file (spring.xml) looks like below.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing 
		infrastructure -->

	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving 
		up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources 
		in the /WEB-INF/views directory -->
	<beans:bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>

	<!-- Configuring interceptors based on URI -->
	<interceptors>
		<interceptor>
			<mapping path="/home" />
			<beans:bean class="com.journaldev.spring.RequestProcessingTimeInterceptor"></beans:bean>
		</interceptor>
	</interceptors>

	<context:component-scan base-package="com.journaldev.spring" />

</beans:beans>

I will not explain all other components of the web application, because we are not interested in them and they don’t have any specific spring interceptor related configuration.

Spring MVC Interceptor Application Testing

Just deploy the application in servlet container and invoke the home controller, you will see logger output something like below.

INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Start Time=1396906442086
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is en_US.
INFO : com.journaldev.spring.HomeController - Before returning view page
Request URL::https://localhost:9090/SpringInterceptors/home Sent to Handler :: Current Time=1396906443098
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: End Time=1396906443171
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Time Taken=1085

The output confirms that the spring interceptor methods are executed in the order defined. That’s all for using spring interceptors, you can download the Spring Interceptor example project from below link and try to have multiple interceptors and check by different order of configuration.

Download Spring Interceptors Project

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Pankaj

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
July 22, 2021

Hi Pankaj, I have multiple APIs with different versions of same resource. /v1/api1/user /v2/api1/user /v3/api1/user Now what I want to do is if I request with /api1/user , I want my application to internally check for latest version(in my case /v3/api1/user) of these api URIs. can we edit this Handler object in preHandle(request,response,handlerObject) and do something that will redirect my API method call to the method configured for /v3/*

- Milan

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    April 20, 2020

    Hi Pankaj, Can you tell me the process if I want the interceptor should be included for more than one service?

    - Prathyusha

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      April 20, 2020

      Can I make this interceptor invoked for more than one rest services of my application?

      - Prathyusha D

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        December 5, 2019

        If the preHandle method throws an exception it is not being processed by the @ExceptionHandler in my @ControllerAdvice class. This @ControllerAdvice class is returning Response objects with HttpStatus suitable for an exception. ErrorDetails is just a pojo of exception class, message, etc which is then automatically converted to json by “Sping Magic”. So what is the best way to get that same “Spring Magic” to turn an exception thrown by the preHandle into the json response with appropriate HttpStatus? Thanks

        - Ian

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          November 5, 2019

          Hi Pankaj, I have an application which track sessions through cookies. When I check rootInterceptor class, I found cookies are null in httpServletRequest, but avilable in httpServletResponse parameter and having value of jsessionid. Not able to understand where it got set. Request your help here.

          - Sanjoy

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            August 31, 2018

            Hi Pankaj, in preHand;le() method , I am checking max inactive Interval time, if it exceeds I am trying to redirect it to login page like public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long startTime = System.currentTimeMillis(); logger.info(“Request URL::” + request.getRequestURL().toString() + “:: Start Time=” +System.currentTimeMillis()); request.setAttribute(“startTime”, startTime); request.logout(); response.sendRedirect(“my full url”) ; return false; } its not redirecting…pls help me

            - mohammed

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              August 30, 2018

              I have classes for systemException and businessException as well as constant file in which success or error messages are stored.But,i don’t know how to use.please,tell me.

              - Ashwini Waghmode

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                August 8, 2018

                How to pass an object from Interceptor to controller?

                - Ran

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  June 16, 2018

                  Hello Pankaj, Thank you for the clear example on spring interceptors. Really appreciate it. My question is on Spring itself really and its enthusiasm for adding a plethora of additional dependencies that potentially clogs up the project over time. I checked the pom file in your project example and there is a lot of “stuff” in there. This is not critique to you, just a question. :) Do you know/have available a bare minimal amount of dependencies that are needed or is this listed dependencies in the project optimal ? BR, Robert

                  - Robert

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    March 11, 2018

                    You are awesome. Never stop writing such awesome blogs.

                    - Rajat Mishra

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Become a contributor for community

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      DigitalOcean Documentation

                      Full documentation for every DigitalOcean product.

                      Resources for startups and SMBs

                      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                      Get our newsletter

                      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                      New accounts only. By submitting your email you agree to our Privacy Policy

                      The developer cloud

                      Scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Get started for free

                      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                      *This promotional offer applies to new accounts only.