Spring Interceptor is similar to a Filter, which is used to intercept the request and process them. Spring MVC allows you to intercept web requests for pre-handling and post-handling through Handler Interceptors.
All the Interceptor class must either implement the HandlerInterceptor interface or extend the HandlerInterceptorAdapter class.
Spring HandlerInterceptor interface declares three methods which can be used do pre-processing and post-processing
- preHandle(): The preHandle() method will be called before the actual handler is executed. This method returns a boolean value which can be used to continue or break the control flowing to the DispatcherServlet.
- postHandle(): The postHandle() method will be called after the handler is executed but before the view being rendered. So, you can add more model objects to the view but you can not change the HttpServletResponse
- afterCompletion(): The afterCompletion() method will be called after the request has completed and the view is rendered.
Folder Structure:
- Create a simple Maven Project “SpringMVCInterceptor” by selecting maven-archetype-webapp and create a package for our source files “com.javainterviewpoint” under src/main/java
- Now add the following dependency in the 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.javainterviewpoint</groupId> <artifactId>SpringMVCInterceptor</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringMVCInterceptor Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <springframework.version>5.1.0.RELEASE</springframework.version> <jstl.version>1.2</jstl.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Spring MVC 5 dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <!-- jstl for jsp page --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.4</version> </dependency> </dependencies> <build> <finalName>SpringMVCInterceptor</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
- Create the Java classes HelloController.java and HelloInterceptor.java under com.javainterviewpoint folder.
- Place the welcome.jsp under /WEB-INF/JSP directory.
- Place the web.xml and SpringConfig.xml under the /WEB-INF directory
Spring Interceptor using HandlerInterceptor
package com.javainterviewpoint; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class HelloInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception { System.out.println("Inside preHandle!!"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView mav) throws Exception { System.out.println("Inside postHandle!!"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object obj, Exception exception) throws Exception { System.out.println("Inside afterCompletion!!"); } }
We have created our HelloInterceptor by implementing HandlerInterceptor and we have overridden the preHandle(), postHandle() and afterCompletion() methods. The HelloInterceptor will be called for all the requests and all the three methods will be executed.
Spring Interceptor using HandlerInterceptorAdapter
When implementing an HandlerInterceptor interface, you must implement all the methods even though you may not have a need for all of them.
A better way is to extend the HandlerInterceptorAdapter class instead. This class implements all the methods by default. You can override only the methods that you need.
In the below code we have overridden only preHandle() and postHandle() methods.
package com.javainterviewpoint; 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 HelloInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception { System.out.println("Inside preHandle!!"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView mav) throws Exception { System.out.println("Inside postHandle!!"); } }
Spring MVC Interceptor Configuration [SpringConfig.xml]
The SpringConfig.xml is also placed under the WEB-INF directory.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd 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"> <context:component-scan base-package="com.javainterviewpoint"> </context:component-scan> <mvc:annotation-driven> </mvc:annotation-driven> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/Jsp/"> </property> <property name="suffix" value=".jsp"> </property> </bean> <mvc:interceptors> <bean class="com.javainterviewpoint.HelloInterceptor"></bean> </mvc:interceptors> </beans>
- We need to redirect all the request through the Spring Interceptor, we will be registering the interceptors using <mvc:interceptors> and HelloInterceptor will be registered as a bean.
- <context:component-scan> will let the Spring Container to search for all the annotation under the package “com.javainteriviewpoint”.
- <mvc:annotation-driven/> annotation will activate the @Controller, @RequestMapping, @Valid etc annotations.
- The view is resolved through “org.springframework.web.servlet.view.InternalResourceViewResolver” which searches for the jsp files under the /WEB-INF/Jsp/ directory.
Equivalent of SpringConfig.xml Java Config
package com.javainterviewpoint; 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 org.springframework.web.servlet.view.JstlView; @EnableWebMvc @Configuration @ComponentScan({"com.javainterviewpoint"}) public class SpringWebMvcConfig extends WebMvcConfigurerAdapter { @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/Jsp"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Bean HelloInterceptor helloInterceptor() { return new HelloInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(helloInterceptor()); } }
HelloWorldExample.java
package com.javainterviewpoint; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { @RequestMapping(value = "/welcome", method = RequestMethod.GET) public ModelAndView welcome() { System.out.println("Inside Controller!!"); return new ModelAndView("welcome"); } }
- We have annotated our “HelloController” class with @Controller annotation which tells Spring Container to treat this class as a Controller.
- @RequestMapping annotation on top of welcome() redirects the request to this method, when the request given is “welcome” and it can take only GET request which is denoted by method=RequestMethod.GET
- Finally return to the view page “welcome” is passed to the ModelAndView class constructor
- Rendering the view will be taken care by “InternalResourceViewResolver” which is configured in our “SpringConfig.xml”
Welcome.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <body> <h1>Spring Interceptor Example</h1> <h3>Welcome to JavaInterviewPoint!!</h3> </body> </html>
web.xml
The web.xml has everything about the application that a server needs to know, which is placed under the WEB-INF directory. <servlet-name> contains the name of the SpringConfiguration, when the DispatcherServlet is initialized the framework will try to load a configuration file “[servlet-name]-servlet.xml” under the WEB-INF directory.
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>SpringConfig</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringConfig</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/SpringConfig.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
Equivalent of web.xml
package com.javainterviewpoint.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { SpringWebMvcConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
Output:
Hit on the URL : http://localhost:8080/SpringMVCInterceptor/welcome
Inside preHandle!! Inside Controller!! Inside postHandle!! Inside afterCompletion!!
Spring Interceptor for specific URL
If suppose you want to restrict the Interceptor to a particular URI that is also possible. You need to configure the <mvc:interceptor> and specify the corresponding URI in the <mvc:mapping>, So when ever the particular URI is accessed then the mapped Spring Interceptor will be called.
In the below configuration the Hello Interceptor will be called when the requested URI is “/hello”, for other URIs the HelloInterceptor will not be called.
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/hello"/> <bean class="com.javainterviewpoint.HelloInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
Spring Interceptor exclude path patterns
You can also define URI exclusion for which the Interceptor should not be called.
If suppose you have 10 URL mapping, except for 1 URL you need to call the Interceptor for the remaining 9 URL mapping, then you can use <mvc:exclude-mapping> to exclude particular URL.
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/student/**"/> <bean class="com.javainterviewpoint.HelloInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
The above configuration will call the Interceptor all the URLs except for the URL pattern /student/**
Equivalent Java Config
@Configuration @EnableWebMvc @ComponentScan({"com.javainterviewpoint"}) public class SpringWebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HelloInterceptor()).addPathPatterns("/**").excludePathPatterns("/student/**"); } }
Leave a Reply