Home > Tutorials > Frameworks > Spring Framework

Spring framework HandlerInterceptor example

Last updated : 20 April 2021

HandlerInterceptor is similar to a Servlet Filter. In addition, HandlerInterceptor allows custom pre-processing with the option to prohibit the execution of the handler itself and custom post-processing. Servlet filters are configured in web.xml while HandlerInterceptors in the application context.

In this article, we will build a simple spring web application to demonstrate how the HandlerInterceptor works. Our application will have a un intercepted page and intercepted page where it checks for login credentials.

What is spring handler interceptor?

Spring HandlerInterceptor can intercept requests to your web application. In a spring web application, an interceptor can intercept requests before the request reaches its designated handler method and before the response is sent to the client. The below figure illustrates how this process works in a spring web application.

Figure 1 : Spring HandlerInterceptor lifecycle

The figure illustrates two client requests. The first request has no interceptor configured. The second request has an interceptor configured. That goes through the handler interceptor process discussed below.

1. The client issue the request to visit the admin page.

2. The dispatcher servlet receives the request. Since the URL /admin is configured to be intercepted, the request is passed through to the pre-handle method of the handler interceptor. (More on how to map URLs listed below)

3. Pre-handle executes applicable logic and passes the request to the designated destination. In our case, it is the admin controller. The controller method executes the necessary logic and sends the response back to the client.

4. The post-handle method intercepts the response and executes applicable logic to modify the response.

5. The client receives the response and completes the rendering process.

6. The after-completion method executes applicable logic to complete the process.

Now let's build a simple project that demonstrates what we discussed so far. All the steps listed below uses the Eclipse IDE.

How to create spring handler interceptor project?

We will create a simple maven webapp and add spring capabilities and handler interceptor to it.

Creating a simple maven webapp

Right-click project explorer New -> Other
or File ->New -> Other
Click Next

Figure : Creating a maven project

Select Maven Project from the wizard
Click Next

Figure : Select maven project

Select a project workspace location
Click Next

Figure : Select maven project workspace

Select maven-archetype-webapp
Click Next

Figure : Select maven webapp

Provide an artifact id
Click Next

Figure : Select maven artifact id

Now your basic web app is ready. If you see any project errors as listed below, follow the instructions provided in Dynamic Web Project with Maven and Eclipse to resolve them.

Figure : Fix maven project errors

Adding spring capabilities to maven webapp

Edit the pom.xml and add spring framework-specific dependencies as below.

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.learnbestcoding</groupId>
  <artifactId>request_interceptors</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>request_interceptors Maven Webapp</name>
  <url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>5.3.5</version>
		</dependency>
		<dependency>
		     <groupId>com.fasterxml.jackson.core</groupId>
		     <artifactId>jackson-databind</artifactId>
		     <version>2.9.2</version>
 		</dependency>
	</dependencies>
  <build>
    <finalName>request_interceptors</finalName>
    <plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
  </build>
</project>

Edit the web.xml file and include the Spring DispatcherServlet. The DispatcherServlet received all the client requests as illustrated in the above figure.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
	<display-name>Archetype Created Web Application</display-name>
	<servlet>
		<servlet-name>request_interceptors</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/applicationContext.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
       <servlet-name>request_interceptors</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Create a spring application context

Create an XML file named applicationContext in the WEB-INF folder. That is where we declare what URLs we want to intercept. More on that later.

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

	<mvc:annotation-driven />
	<context:component-scan base-package="com.web,com.util" />
	<mvc:default-servlet-handler />	
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
          <property name="prefix"><value>/WEB-INF/jsp/</value></property>
          <property name="suffix"><value>.jsp</value></property>
    </bean>
</beans>

Create controller and value object class

Our controller class resides in com.web, and AdminVo resides in com.util packages, respectively.

package com.web;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.util.AdminVO;

@Controller
public class AdminController{
	
	 @RequestMapping(value = "adminLogin")
	 public String adminLogin() throws IOException
	 {
		return "adminLogin";
	 }	 
	 @RequestMapping(value = "/intercept/authenticate")
	 public void authenticate(HttpServletRequest request, HttpServletResponse response, @ModelAttribute AdminVO vo) throws IOException
	 {
		if("LearnBestCoding".equals(vo.getUserName())) {
			request.getSession().setAttribute("adminvo", vo); 
			response.sendRedirect("/request_interceptors/intercept/adminPage");
		}
		else {
			response.sendRedirect("adminLogin");
		}		
	 }	 
	 @RequestMapping(value = "/intercept/adminPage")
	 public String adminPage(HttpServletRequest request) throws IOException
	 {
		 return "adminPage";
	 }	 
	 @RequestMapping(value = "/logout")
	 public String logout(HttpServletRequest request) throws IOException
	 {
		 request.getSession().removeAttribute("adminvo");
		 return "adminLogin";
	 }
}
package com.util;

public class AdminVO {
	String userName;
	String password;
	
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public boolean isAuthenticated() {
		return authenticated;
	}
	public void setAuthenticated(boolean authenticated) {
		this.authenticated = authenticated;
	}
	boolean authenticated;
}

Create jsp's to render view

We will secure adminPage.jsp by intercepting requests to it. If the user is not authenticated, the user will be redirected to adminLogin.jsp to authenticate. Now create adminPage.jsp and adminLogin.jsp in WEB-INF/jsp folder.

<html>
<body>
<h2>Hello ${adminvo.userName}!</h2>
<table>
<tr><td>${postHandle}</td></tr>
<tr><td>Click <a href='/request_interceptors/logout'>here</a> to log out.</td></tr>
</table>
</body>
</html>
<html>
<body>
<h2>Login Page</h2>
<form action="/request_interceptors/intercept/authenticate" method="POST">
<table>
<tr><td>Enter user name:</td><td><input type="text" name="userName" size="20"></td></tr>
<tr><td>Enter password:</td><td><input type="password" name="password" size="20"></td></tr>
<tr><td colspan="2"><input type="submit" value="Submit" /></td></tr>
</table>
</form>
</body>
</html>

Create HandlerInterceptor class

Out interceptor class name is LinkInterceptor. It resides in the com.util folder. Note that logic in preHandle and postHandle methods alter the request and add additional attributes.

package com.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LinkInterceptor implements HandlerInterceptor{
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView){
		request.setAttribute("postHandle", "Message from postHandle method");
	}
	   	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if(request.getRequestURI().contains("authenticate"))
		{
			return true;
		}
		if(request.getRequestURI().contains("adminPage"))
		{
			if(request.getSession().getAttribute("adminvo") != null)
			{
				return true;
			}
			else
			{
				response.sendRedirect("/request_interceptors/adminLogin");
				return false;
			}
		}
		else
		{
			return true;
		}
	}
	
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
		System.out.println("The http status for : " + request.getRequestURL() +" is : "+   response.getStatus());
	}
}

How to intercept request URLs with HandlerInterceptor?

In order to intercept URLs, we can use <mvc:interceptors> in the applicationContext.xml. Within the <mvc:interceptors>, you can declare multiple interceptors. Note that <mvc:mapping> is the key to specify the exact URL patterns we want to intercept. Each specified URL pattern is intercepted by the declared interceptor class within the <mvc:interceptor>. In this example, all URLs containing */intercept/* in the URL are intercepted by the LinkInterceptor.

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

	<mvc:annotation-driven />
	<context:component-scan base-package="com.web,com.util" />
	<mvc:default-servlet-handler />	
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
          <property name="prefix"><value>/WEB-INF/jsp/</value></property>
          <property name="suffix"><value>.jsp</value></property>
    </bean>
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/intercept/**" />
			<bean class="com.util.LinkInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>
</beans>

Each intercepted URL will go through preHandle and postHandle methods. The afterCompletion is triggered upon completion of the rendering process.

Example output of our demo webapp with HandlerInterceptor

Our login page and admin page will look like below. Note that the admin page is only accessible once the login credentials are validated.

Figure : Login page (not intercepted)
Figure : Admin page (intercepted)

If you attempt to access the admin page by directly typing the URL http://localhost:8090/request_interceptors/intercept/adminPage, you will notice that the interceptor redirects the user back to the login page.

Lance
By: Lance
Lance is a software engineer with over 15 years of experience in full-stack software development.
Read more...

Comments are disabled

No Comments