Spring Boot HandlerInterceptor Example

In this post we will discuss about spring boot HandlerInterceptor integration example with WebMvcConfigurerAdapter .Handler interceptors are used when you want to apply specific functionality to certain or all requests. Handler Interceptors should implement the interface HandlerInterceptor. HandlerInterceptor can be used to avoid repetitive handler code. We can use HandlerInterceptor for different purposes like authorization checks, locale checks , logging , creating common application parameters etc.

HandlerInterceptor works similar to the servlet filter. But in some cases filters are more powerful than HandlerInterceptor. In Spring-MVC the HandlerInterceptor is configured in spring application context xml file or by Java configuration. Here in this post we will see , how to configure a HandlerInterceptor with Spring-Boot application. HandlerInterceptor has three methods. 

preHandle( ) : It is executed before actual handler is executed. 
postHandle( ) : It is executed after handler is executed. 
afterCompletion( ) : It is executed after the complete request is finished. 

Following is the Structure of our Spring boot application.

To create the Spring-Boot application with an Interceptor we need the following dependencies to be added in pom.xml.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.tuturself</groupId>
<artifactId>spring-boot-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.1.RELEASE</version>
</parent>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>com.jayway.jsonpath</groupId>
		<artifactId>json-path</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<properties>
	<java.version>1.8</java.version>
</properties>


<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

<repositories>
	<repository>
		<id>spring-releases</id>
		<url>https://repo.spring.io/libs-release</url>
	</repository>
</repositories>
<pluginRepositories>
	<pluginRepository>
		<id>spring-releases</id>
		<url>https://repo.spring.io/libs-release</url>
	</pluginRepository>
</pluginRepositories>
</project>

Here we are creating a Person Search API with spring boot. In the POST Building an Application with Spring Boot  we have already discussed about creating an Spring Boot application. Refer the post if you are new in Spring Boot. Following is our main Application class SpringBootWebApplication. Here the main application class is annotated as @SpringBootApplication . The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes:

package com.tuturself.springboot.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.tuturself.springboot.web.service.PersonService;

@SpringBootApplication
public class SpringBootWebApplication {

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

	/**
	 * Defining the bean {@link PersonService}
	 * 
	 * @return {@link PersonService}
	 */
	@Bean
	public PersonService personService() {
		return new PersonService();
	}
}

Following is our controller class PersonAPI. This class is actually exposing the REST API for searching a Person. In Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. These components are easily identified by the @RestController annotation, and the PersonAPI Controller below handles GET requests for /search/person by returning a Person Object. @RestController is Spring 4’s new annotation, which marks the class as a controller where every method returns a domain object instead of a view. It’s shorthand for @Controller and @ResponseBody rolled together.

package com.tuturself.springboot.web.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.tuturself.springboot.web.model.Person;
import com.tuturself.springboot.web.service.PersonService;

@RestController
@RequestMapping("/search")
public class PersonAPI {

	@Autowired
	private PersonService personService;

	@RequestMapping("/person")
	public Person searchStudent(@RequestParam(name = "personId", required = true) 
				Integer personId) {
		Person person = personService.getPersonById(personId);
		return person;
	}
}

Following is the Person domain Object. This is a simple old Java POJO class.

package com.tuturself.springboot.web.model;

public class Person {

	private Integer personId;
	private String name;
	private Long ssn;
	
	public Person(Integer personId, String name, Long ssn) {
		super();
		this.personId = personId;
		this.name = name;
		this.ssn = ssn;
	}

	public Integer getPersonId() {
		return personId;
	}

	public void setPersonId(Integer personId) {
		this.personId = personId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Long getSsn() {
		return ssn;
	}

	public void setSsn(Long ssn) {
		this.ssn = ssn;
	}
}

Following is the Service class PersonService. Which is searching for the Person Object from the database. Here we have used a Mock HashMap as our data store for the sake of simplicity. At @PostConstruct the dummy Person database will be populated.  @PostConstruct get called automatically when the bean initialization completed. To read more about spring lifecycle callbacks like @PostConstruct read here.

package com.tuturself.springboot.web.service;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

import com.tuturself.springboot.web.model.Person;

public class PersonService {

	private static Map personDB;

	@PostConstruct
	public void init() throws Exception {
		personDB = new HashMap<>();
		for (int i = 0; i < 100; i++) {
			Person person = new Person(i, "Person-name-" + i, System.currentTimeMillis());
			personDB.put(new Integer(i), person);
		}
	}

	public Person getPersonById(Integer id) {
		return personDB.get(id);
	}
}

Now we need to configure the HandlerInterceptor with our application. We will create the Interceptor by extending the HandlerInterceptorAdapter. By Using adapter class, we can implement only required methods. But in our example, we are going to override all the three methods preHandle(), postHandle() and afterCompletion(). Spring also provides as interface HandlerInterceptor. Which we can implement to create our interceptor. But in that case it is mandatory to implement all the 3 methods. Following is the interceptor for our example.

package com.tuturself.springboot.web.interceptor;

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

import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

@Component
public class RequestInterceptor extends HandlerInterceptorAdapter {

 /**
 * This is not a good practice to use sysout. Always integrate any logger
 * with your application. We will discuss about integrating logger with
 * spring boot application in some later article
 */
 @Override
 public boolean preHandle(HttpServletRequest request, 
		HttpServletResponse response, Object object) throws Exception {
	System.out.println("In preHandle we are Intercepting the Request");
	System.out.println("____________________________________________");
	String requestURI = request.getRequestURI();
	Integer personId = ServletRequestUtils.getIntParameter(request, "personId", 0);
	System.out.println("RequestURI::" + requestURI + 
			" || Search for Person with personId ::" + personId);
	System.out.println("____________________________________________");
	return true;
 }

 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, 
		Object object, ModelAndView model)
		throws Exception {
	System.out.println("_________________________________________");
	System.out.println("In postHandle request processing "
			+ "completed by @RestController");
	System.out.println("_________________________________________");
 }

 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
		Object object, Exception arg3)
		throws Exception {
	System.out.println("________________________________________");
	System.out.println("In afterCompletion Request Completed");
	System.out.println("________________________________________");
 }
}

Now we need to integrate this interceptor with our Spring application. We will tell spring to execute the methods at time when request comes to our PersonAPI. To do the same we will create a AppConfig class which extends the WebMvcConfigurerAdapter class. In this configuration class to add our interceptor, we override WebMvcConfigurerAdapter. addInterceptors() method. Find the code snippet :

package com.tuturself.springboot.web.configuration;

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.WebMvcConfigurerAdapter;

import com.tuturself.springboot.web.interceptor.RequestInterceptor;

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {

	@Autowired
	RequestInterceptor requestInterceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(requestInterceptor);
	}
}

This class is annotated as @Configuration. Now our application is ready. Build it and try to run it. Run the SpringBootWebApplication class. You can see the following in console.

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.1.RELEASE)

2017-03-10 17:12:14.165  INFO 7576 --- [           main] c.t.s.web.SpringBootWebApplication      
: Starting SpringBootWebApplication

Now when the application is up, try the following url in your browser. http://localhost:8080/search/person?personId=12. At this point you will get the following output in browser if all goes well :)

{"personId":12,"name":"Person-name-12","ssn":1489146135530}

Now check the log again in console to understand the flow of your interceptor.

In preHandle we are Intercepting the Request
____________________________________________
RequestURI::/search/person || Search for Person with personId ::12
____________________________________________
______________________________________________________________
In postHandle request processing completed by @RestController
______________________________________________________________
______________________________________________________________
In afterCompletion Request Completed
______________________________________________________________

The preHandle executed first and then request goes to @RestController. postHandle executed when the controller is done and the afterCompletion is executed when the request is completed. Happy learning and be with us for more post with Spring-Boot.

To Download the source code from GitHub Check the following link:

https://github.com/ninja-panda/spring-boot-example/tree/master/spring-boot-web

spring 12 Spring Boot 12

FOLLOW US ON LinkedIn



Explore Tutu'rself