Spring MVC 4 - How to intercept request with a HandlerInterceptor

Posted on September 2, 2017


Technologies used: Java SE 1.8 | Spring 4.3.10.RELEASE | Maven 3.3.9 | Eclipse Neon.3 | Apache Tomcat  7.0.47

In this post, I will show you how to use the HandlerInterceptor interface and HandlerInterceptorAdapter class in Spring MVC application to intercept the web requests.

The HandlerInterceptor interface has three abstract methods as-

  • preHandle() - It is called before the handler method of a controller class is invoked.
  • afterCompletion() - It is called after completion of a request i.e. after render the view. 
  • postHandle() - It is called after the handler method of a controller class is invoked, but before rendering the view.

The HandlerInterceptorAdapter class is an implementation of the HandlerInterceptor interface, so use this class if you want to override the specific method.

To create a custom handler interceptor, you can use either the HandlerInterceptor interface or HandlerInterceptorAdapter class. Let’s see the complete example to demonstrate the above.

Project structure

Review the following web project structure build using Maven.

Spring-mvc-handler-interceptor.png

Related - How to create a web project using maven build tool in eclipse IDE.

Jar dependencies

Open pom.xml file of your maven project and add the following dependencies in it.

<dependencies>
  <!-- Spring MVC Dependency -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.10.RELEASE</version>
  </dependency>
  <!-- JSTL Dependency -->
  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>javax.servlet.jsp.jstl-api</artifactId>
    <version>1.2.1</version>
  </dependency>
  <dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
  </dependency>
  <!-- Servlet Dependency -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <!-- JSP Dependency -->
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.1</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

Custom handler interceptor

Create a handler interceptor class, named as GuestInterceptor, by implementing the HandlerInterceptor interface as follows.

GuestInterceptor.java

package com.boraji.tutorial.spring.interceptor;

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

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class GuestInterceptor implements HandlerInterceptor {

   // Called before handler method invocation
   @Override
   public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
         Object handler) throws Exception {
      System.out.println("Called before handler method");
      req.setAttribute("fname", "Elizabeth");
      return true;
   }

   // Called after handler method request completion, before rendering the view
   @Override
   public void postHandle(HttpServletRequest req, HttpServletResponse res, 
         Object handler, ModelAndView model)  throws Exception {
      System.out.println("Called after handler method request completion,"
            + " before rendering the view");

      model.addObject("lname", "Brown");
   }

   // Called after rendering the view
   @Override
   public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
         Object handler, Exception ex)  throws Exception {
      System.out.println("Called after rendering the view");
   }
}

Now, create another handler interceptor class, named as AdminInterceptor, by extending the HandlerInterceptorAdapter class and override the postHandle() method as follows.

AdminInterceptor.java

package com.boraji.tutorial.spring.interceptor;

import java.time.LocalTime;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class AdminInterceptor extends HandlerInterceptorAdapter {

   @Override
   public void postHandle(HttpServletRequest req, HttpServletResponse res,
         Object handler, ModelAndView model)  throws Exception {

      System.out.println("Called after handler method request completion,"
            + " before rendering the view");

      LocalTime time = LocalTime.now();
      int hrs = time.getHour();
      if (hrs >= 0 && hrs <= 12) {
         model.addObject("greeting", "Good morning!");
      } else if (hrs > 12 && hrs <= 17) {
         model.addObject("greeting", "Good afternoon!");
      } else {
         model.addObject("greeting", "Good evening!");
      }
   }
}

 

Spring configuration + Registering interceptors

Create a web @Configuration class annotated with @EnableWebMvc and @ComponentScan.

Override the addInterceptors() method of the WebMvcConfigurerAdapter class to register the custom handler interceptors GuestInterceptor and AdminInterceptor as follows.

WebConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.boraji.tutorial.spring.intercepter.AdminIntercepter;
import com.boraji.tutorial.spring.intercepter.GuestIntercepter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      // Register guest interceptor with single path pattern
      registry.addInterceptor(new GuestInterceptor()).addPathPatterns("/guest");

      // Register admin interceptor with multiple path patterns
      registry.addInterceptor(new AdminInterceptor())
              .addPathPatterns(new String[] { "/admin", "/admin/*" });
   }

   @Bean
   public InternalResourceViewResolver resolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setPrefix("/WEB-INF/views/");
      resolver.setSuffix(".jsp");
      return resolver;
   }

}

Controller class

Create a simple UserController class to handle the requests for guest and admin users.

UserController.java

package com.boraji.tutorial.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

   @RequestMapping("/")
   public String index() {
      return "index";
   }

   @RequestMapping("/guest")
   public String guestHandler(@RequestAttribute("fname")String fname,Model model) {
      model.addAttribute("mname", "Smith");
      return "guest";
   }

   @RequestMapping("/admin")
   public String adminHandler(Model model) {
      model.addAttribute("name", "Mike");
      return "admin";
   }
}

JSP Views

Create a new folders as \WEB-INF\views under src\main\webapp folder. 

Now, create index.jspguest.jsp and admin.jsp files under src\main\webapp\WEB-INF\views under folder.

index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
</head>
<body>
  <h2>Spring MVC 4 - HandlerInterceptor example</h2>
  <p>
    <a href="guest">Guest</a> | <a href="admin">Admin</a>
  </p>
</body>
</html>

guest.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
</head>
<body>
  <h2>Spring MVC 4 - HandlerInterceptor example</h2>
  <h3>Guest user name is : ${fname} ${mname} ${lname}</h3>
</body>
</html>

admin.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
</head>
<body>
  <h2>Spring MVC 4 - HandlerInterceptor example</h2>
  <h3>${greeting} ${name}</h3>
</body>
</html>

Servlet container initialization

Finally, create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer to bootstrap the Spring MVC application.

MyWebAppInitializer.java

package com.boraji.tutorial.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] {};
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

The AbstractAnnotationConfigDispatcherServletInitializer class, implements the WebApplicationInitializer, is implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically. 

 

Build + Deploy + Run application

Use the following maven commands to build, package, deploy and run application.

mvn clean install  (This command triggers war packaging)

mvn tomcat7:run (This command run embedded tomcat and deploy war file automatically)

You can refer this link to learn how to run the above commands in Eclipse IDE.

 

Type the following URLs in browser's address bar to open the home page.

http://localhost:8080/

Spring-mvc-handler-interceptor01.png

Now click on the 'Guest' link to open the guest page.

Spring-mvc-handler-interceptor02.png

Now go to home page and click on the 'Admin' link to open the admin page.

Spring-mvc-handler-interceptor03.png