Spring Interceptor are used to intercept client requests and process them. Sometimes we want to intercept the HTTP Request and do some processing before handing it over to the controller handler methods. That’s where Spring MVC Interceptor come handy.
Just like we have Struts2 Interceptors, we can create our own Spring interceptor by either implementing org.springframework.web.servlet.HandlerInterceptor
interface or by overriding abstract class org.springframework.web.servlet.handler.HandlerInterceptorAdapter
that provides the base implementation of HandlerInterceptor interface.
Spring HandlerInterceptor declares three methods based on where we want to intercept the HTTP request.
If there are multiple spring interceptors configured, preHandle() method is executed in the order of configuration whereas postHandle() and afterCompletion() methods are invoked in the reverse order. Let’s create a simple Spring MVC application where we will configure an Spring Interceptor to log timings of controller handler method. Our final Spring Interceptor example project will look like below image, we will look into the components that we are interested in.
package com.journaldev.spring;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = "/home", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
//adding some time lag to check interceptor execution
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
logger.info("Before returning view page");
return "home";
}
}
I am just adding some processing time in the execution of the handler method to check our spring interceptor methods in action.
For simplicity, I am extending abstract class HandlerInterceptorAdapter
. HandlerInterceptorAdapter is abstract adapter class for the HandlerInterceptor interface, for simplified implementation of pre-only/post-only interceptors.
package com.journaldev.spring;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class RequestProcessingTimeInterceptor extends HandlerInterceptorAdapter {
private static final Logger logger = LoggerFactory
.getLogger(RequestProcessingTimeInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
long startTime = System.currentTimeMillis();
logger.info("Request URL::" + request.getRequestURL().toString()
+ ":: Start Time=" + System.currentTimeMillis());
request.setAttribute("startTime", startTime);
//if returned false, we need to make sure 'response' is sent
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Request URL::" + request.getRequestURL().toString()
+ " Sent to Handler :: Current Time=" + System.currentTimeMillis());
//we can add attributes in the modelAndView and use that in the view page
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
long startTime = (Long) request.getAttribute("startTime");
logger.info("Request URL::" + request.getRequestURL().toString()
+ ":: End Time=" + System.currentTimeMillis());
logger.info("Request URL::" + request.getRequestURL().toString()
+ ":: Time Taken=" + (System.currentTimeMillis() - startTime));
}
}
The logic is really simple, I am just logging the timings of handler method execution and total time taken in processing the request including rendering view page.
We have to wire the spring interceptor to the requests, we can use mvc:interceptors element to wire all the interceptors. We can also provide URI pattern to match before including the spring interceptor for the request through mapping element. Our final spring bean configuration file (spring.xml) looks like below.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- Configuring interceptors based on URI -->
<interceptors>
<interceptor>
<mapping path="/home" />
<beans:bean class="com.journaldev.spring.RequestProcessingTimeInterceptor"></beans:bean>
</interceptor>
</interceptors>
<context:component-scan base-package="com.journaldev.spring" />
</beans:beans>
I will not explain all other components of the web application, because we are not interested in them and they don’t have any specific spring interceptor related configuration.
Just deploy the application in servlet container and invoke the home controller, you will see logger output something like below.
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Start Time=1396906442086
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is en_US.
INFO : com.journaldev.spring.HomeController - Before returning view page
Request URL::https://localhost:9090/SpringInterceptors/home Sent to Handler :: Current Time=1396906443098
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: End Time=1396906443171
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Time Taken=1085
The output confirms that the spring interceptor methods are executed in the order defined. That’s all for using spring interceptors, you can download the Spring Interceptor example project from below link and try to have multiple interceptors and check by different order of configuration.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Hi, when I am getting the parameter value from request, its a null value. so how should I get the parameter value in interceptor.
- Ram
Thanks ! Simple and intuitive !
- Evgeny
The presence of so many logging dependencies and exclusions is amazing. Even such a tiny app. required … 7!!! Artifacts. Surely that was not what logging was meant to be. But this is what is wrong with open source in general.
- Pupsick
Problem : I am calling spring controller using curl request. As Input I am passing a json with request to controller. Now I just want to fetch that json inside spring interceptor .But it is not working for me. Enumeration en=request.getParameterNames(); System.out.println(Collections.list(en).size()); It is giving zero size. Please take a look.
- Rita
How to modify the respone ?
- lastspring
How to use @Autowired service in handler…If i am using then null pointer exception will occur
- Akhil
how to apply logging interceptor for all methods what should i do. like ,for create we use following " " if i want do this fr all what should i do
- akash
You are awesome. Never stop writing such awesome blogs.
- Rajat Mishra
Hello Pankaj, Thank you for the clear example on spring interceptors. Really appreciate it. My question is on Spring itself really and its enthusiasm for adding a plethora of additional dependencies that potentially clogs up the project over time. I checked the pom file in your project example and there is a lot of “stuff” in there. This is not critique to you, just a question. :) Do you know/have available a bare minimal amount of dependencies that are needed or is this listed dependencies in the project optimal ? BR, Robert
- Robert
How to pass an object from Interceptor to controller?
- Ran