Interceptors in Spring

In Spring, Interceptors, as the name suggests, intercept we requests through implementing HandlerInterceptor interface. It provides us with methods that allow us to intercept incoming requests that is getting processed by the controller class or the response that has been processed by the controller class.

java-featured-image

The methods that the interface provides us with are:

  1. preHandle() – returns true or false. If it returns true, then the handler execution chain continues, stops otherwise.
  2. postHandle() – called after the handler execution.
  3. afterCompletion() – called after the request has finished and the view was generated.

HandlerInterceptor vs HandlerInterceptorAdapter

In the beginning, I said that we need to implement HandlerInterceptor interface, however we can also implement HandlerInterceptorAdapter. There is 1 difference between them and that is that HandlerInterceptor we have to override all three methods that I mentioned above while the HandlerInterceptorAdapter allows us to override only the required methods.



Code implementation

Usually, the workflow for these 3 methods is throwing an Exception or returning true.

@Component
public class EmployeeInterceptor implements HandlerInterceptor {
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {
	   // Basic validation of password and username
	   String username = request.getParameter("username");
	   String password = request.getParameter("password");
	   
	   if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
	      // throw the exception
		  throw new Exception("Empty username or password.");
	   }
	   
	   // if no exception has been thrown, return true
	   return true;
	}
	
	@Override
	public boolean postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {
	   log.info(request);
	   return true;
    }				

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
									Object handler, Exception exc) throws Exception {
	   if (exc != null) 
	      exc.printStackTrace();
	   else
          log.info("Request: " + request + " / Exception: " + exc); 
	}
}

Let’s break down the code example above.

First we create our class and it implements HandlerInterceptor because it overrides all three methods. As a convention, the class name has to have Interceptor after the initial name. Then, we override preHandle() method. It takes 3 parameters – request, response and handler and don’t forget the throws Exception. 

preHandle()

My preHandle() method is pretty simple – it fetches the username and password from the requests then checks if they are empty and if they indeed are, then throw an exception stating “Empty username or password.”. If they are not empty, return true. In normal environment, you will do much more validation of course, but I made it like that for the sake of simplicity.

postHandle()

My postHandle() method does not do much at all a part from returning true if there has not been thrown an exception and logs the request. It takes 4 parameters – request, response, handler and modelAndView. It also throws Exception. Usually this method is used to modify the ModelAndView (usually by adding additional attributes) or to simply determine the time that has taken the handler method to process a client’s request.

afterCompletion()

My afterCompletion() method logs the request and the exception but before that, it checks if there have been any exceptions by saying exc != null and if there have been, then we say exc.printStackTrace().

Configuration

Our interceptor is not yet added into the Spring configuration. To add it, we have to implement a custom @Configuration file which extends WebMvcConfigurerAdapter which adds the interceptor within the addInterceptors method.

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(new EmployeeInterceptor()).addPathPatterns("/account/signin/process");
   }
}

Also, keep in mind you have to specify the appropriate path pattern in the addInterceptors method.

 

Leave a Reply

avatar