Spring MVC Handler Interceptors Example
With this tutorial we shall explain how to make use of Spring MVC handler interceptors. Handler interceptors are provided by Spring’s handler mapping mechanism, and they can be used to apply a certain functionality to requests. For example, an interceptor may be used to check for a principal.
In order to create a handler interceptor, we must make use of org.springframework.web.servlet.HandlerInterceptor
. A custom interceptor must implement this interface. The HandlerInterceptor
defines three methods that can be used for preprocessing and postprocessing requests:
preHandle(..)
is called before the actual handler is executed. It returns a boolean value. When it returns true, the handler execution chain continues, whereas when it returns false, theDispatcherServlet
assumes the interceptor itself has taken care of requests (and, for example, rendered an appropriate view) and does not continue executing the other interceptors and the actual handler in the execution chain.postHandle()
is called after the handler is executed.afterCompletion()
is called after the complete request has finished.
Here, we will create an interceptor implementation, that makes use of preHandle()
and postHandle()
methods. We will create a simple project with a Controller
, an interceptor, a view
(jsp) and we will add the necessary configuration files. Then we will use an application server to run the example. The interceptor will keep time in ms every time it is invoked (before and after the controller invocation).
You may skip project creation and jump directly to the example code section below.
Our preferred development environment is Eclipse. We are using Eclipse Juno (4.2) version, along with Maven Integration plugin version 3.1.0. You can download Eclipse from here and Maven Plugin for Eclipse from here. The installation of Maven plugin for Eclipse is out of the scope of this tutorial and will not be discussed. We are also using JDK 7_u_21. Tomcat 7 is the application server used.
Let’s begin,
1. Create a new Maven project
Go to File -> Project ->Maven -> Maven Project.
In the “Select project name and location” page of the wizard, make sure that “Create a simple project (skip archetype selection)” option is unchecked, hit “Next” to continue with default values.
Here the maven archetype for creating a web application must be added. Click on “Add Archetype” and add the archetype. Set the “Archetype Group Id” variable to "org.apache.maven.archetypes"
, the “Archetype artifact Id” variable to "maven-archetype-webapp"
and the “Archetype Version” to "1.0"
. Click on “OK” to continue.
In the “Enter an artifact id” page of the wizard, you can define the name and main package of your project. Set the “Group Id” variable to "com.javacodegeeks.snippets.enterprise"
and the “Artifact Id” variable to "springexample"
. The aforementioned selections compose the main project package as "com.javacodegeeks.snippets.enterprise.springexample"
and the project name as "springexample"
. Set the “Package” variable to "war"
, so that a war file will be created to be deployed to tomcat server. Hit “Finish” to exit the wizard and to create your project.
The Maven project structure is shown below:
- It consists of the following folders:
- /src/main/java folder, that contains source files for the dynamic content of the application,
- /src/test/java folder contains all source files for unit tests,
- /src/main/resources folder contains configurations files,
- /target folder contains the compiled and packaged deliverables,
- /src/main/resources/webapp/WEB-INF folder contains the deployment descriptors for the Web application ,
- the pom.xml is the project object model (POM) file. The single file that contains all project related configuration.
2. Add Spring-MVC dependencies
Add the dependencies in Maven’s pom.xml
file, by editing it at the “Pom.xml” page of the POM editor. The dependency needed for MVC is the spring-webmvc
package, and the javax.servlet
package. We also use the log4j package, so that the controller and the interceptor will log messages, when invoked.
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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks.snippets.enterprise</groupId> <artifactId>springexample</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>springexample Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <build> <finalName>springexample</finalName> </build> <properties> <spring.version>3.2.3.RELEASE</spring.version> </properties> </project>
3. Create a Controller – View – Model example
The HelloWorldController
extends the AbstractController
provided by Spring, and overrides the handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
method, where a org.springframework.web.servlet.ModelAndView
is created by a handler and returned to be resolved by the DispatcherServlet
. The method also logs a message when invoked.
HelloWorldController.java
package com.javacodegeeks.snippets.enterprise; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class HelloWorldController extends AbstractController{ private static final Logger logger = Logger.getLogger(HelloWorldController.class); @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView model = new ModelAndView("helloWorld"); model.addObject("msg", "hello world!"); logger.info("Hello World Controller is invoked! "); return model; } }
The view is a simple jsp page, that shows the value of the attribute that was set to the HelloWorldController
. It must be placed in /WEB-INF/
folder.
helloWorld.jsp
<html> <body> <h1>Spring 3.2.3 MVC web service</h1> <h3>Your message is : ${msg}</h3> </body> </html>
The files that we must configure in the application are the web.xml
file and the mvc-dispatcher-servlet.xml
file.
The web.xml
file is the file that defines everything about an application that a server needs to know. It is placed in /WEB-INF/
directory of the application. The <servlet>
element declares the DispatcherServlet
. When the DispatcherServlet
is initialized, the framework will try to load the application context from a file named [servlet-name]-servlet.xml
located in /WEB-INF/
directory. So, we have created the mvc-dispatcher-servlet.xml
file, that will be explained below. The <servlet-mapping>
element of web.xml
file specifies what URLs will be handled by the DispatcherServlet
.
web.xml
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
The mvc-dispatcher-servlet.xml
is also placed in /WEB-INF
directory. The org.springframework.web.servlet.view.InternalResourceViewResolver
is defined as a bean, and is used as internal resource views resolver, meaning that it will find the jsp and html files in the /WEB-INF/
folder. We can set properties such as prefix
or suffix
to the view name to generate the final view page URL. The controller bean is defined here too. The org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
class is used to map URL requests to the controller.
mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <bean name="/helloWorld.htm" class="com.javacodegeeks.snippets.enterprise.HelloWorldController" /> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> </bean> </beans>
4. Create an interceptor
TimeInterceptor.java
class is an interceptor that implements the org.springframework.web.servlet.handler.HandlerInterceptorAdapter
interface. It overrides the preHandle()
and postHandle()
methods, where a log message is produced with the time that every method is invoked.
TimeInterceptor.java
package com.javacodegeeks.snippets.enterprise; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class TimeInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = Logger.getLogger(TimeInterceptor.class); public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long time = System.currentTimeMillis(); request.setAttribute("time", time); logger.info(" pre handle method, time in ms is: "+ time); return true; } public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { long totalTime = System.currentTimeMillis() - (Long)request.getAttribute("time"); modelAndView.addObject("totalTime", totalTime); logger.info(" post handle method, totalTime passed: " + totalTime + "ms" ); } }
5. Configure the interceptor
The interceptor must be configured in the mvc-dispatcher-servlet.xml
file. All HandlerMapping
classes extending from AbstractHandlerMapping
have an interceptors
property, where the interceptor bean is defined through the ref
tag.
mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <bean name="/helloWorld.htm" class="com.javacodegeeks.snippets.enterprise.HelloWorldController" /> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="timeInterceptor" /> </list> </property> </bean> <bean id="timeInterceptor" class="com.javacodegeeks.snippets.enterprise.TimeInterceptor"> </bean> </beans>
6. Run the application
After building the project with Maven (Right click -> Run as -> Maven build), a .war
file is produced. We can place it in /webapps
folder of tomcat, and then we can start tomcat server.
Then, hitting on :
http://localhost:8080/springexample/helloWorld.htm
The result of the view is the one below:
Whereas, in tomcat logs we can see the interceptor log messages before and after the controller log message:
This was an example of how to create a use an MVC handler interceptor in Spring.
Download source code of this tutorial: SpringMVCHandlerInterceptorExample.zip