Detail the use of the Interceptor interceptor in SpringMVC

  • 2020-05-26 09:14:52
  • OfStack

The Interceptor interceptor in SpringMVC is also quite important and useful. Its main function is to intercept user requests and process them accordingly. For example, it can be used for permission verification, or it can be used to determine whether the user is logged in, or it can be used to determine whether the current time is the time of ticket purchase like 12306.

1. Define the Interceptor implementation class

In SpringMVC, Interceptor intercepts requests through HandlerInterceptor. There are two main ways to define Interceptor in SpringMVC. The first way is that the Interceptor class to be defined implements Spring's HandlerInterceptor interface, or the class that this class inherits implements HandlerInterceptor interface, such as HandlerInterceptorAdapter, the abstract class that Spring has provided that implements HandlerInterceptor interface. The second way is to implement Spring's WebRequestInterceptor interface, or to inherit classes that implement WebRequestInterceptor.

(1) implement HandlerInterceptor interface

The HandlerInterceptor interface defines three methods that we use to intercept user requests.

(1) the preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) method, which, as the name implies, is called before the request is processed. Interceptor in SpringMVC is chain-call, in one application or in one request can exist at the same time multiple Interceptor. Each Interceptor calls are executed according to its statement sequence, and the first to perform is the preHandle Interceptor method, so can be 1 in this method some front initialization or is a pretreatment for the current request, also can undertake more judgment in this method to decide whether the request to proceed.

The return value of this method is of Boolean type Boolean. When it returns false, it means that the request ends, and the subsequent Interceptor and Controller will not be executed. When the return value is true, the next Interceptor preHandle method will be called, and if it is the last Interceptor method, the current Controller method will be called.

(2) postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) method. We know from the explanation of the preHandle method that this method, including the afterCompletion method mentioned below, can only be called if the return value of the preHandle method belonging to Interceptor is true.

The postHandle method, as the name implies, is executed after the current request is processed, that is, after the Controller method is called, but it is called before DispatcherServlet does the view return rendering, so we can manipulate the ModelAndView object after Controller processing in this method. The postHandle method is called in the opposite direction to preHandle, that is to say, the postHandle method of Interceptor declared first will be executed after the event, which is somewhat similar to the execution of Interceptor in Struts2. The execution process of Interceptor in Struts2 is also chained, except that in Struts2, ActionInvocation's invoke method needs to be manually called to trigger the next Interceptor or Action call, and then the contents before invoke method call in each Interceptor are executed in the declared order, while the contents after invoke method are reversed.

(3) afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) method, which also needs to be executed when the return value of the current Interceptor preHandle method is true. As the name implies, this method is executed after the entire request has been completed, that is, after DispatcherServlet has rendered the corresponding view. The main purpose of this method is to clean up the resources.

Here is a simple code description:


import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import org.springframework.web.servlet.HandlerInterceptor; 
import org.springframework.web.servlet.ModelAndView; 
 
public class SpringMVCInterceptor implements HandlerInterceptor { 
 
 
  /** 
   * preHandle Method is used for processor interception and, as the name implies, the method will be used in Controller Call before processing, SpringMVC In the Interceptor Interceptors are chained and can exist simultaneously  
   *  multiple Interceptor And then SpringMVC Will be based on the sequence of statements 1 after 1 The execution of one, and all of them Interceptor In the preHandle The method will be  
   * Controller Call before method call. SpringMVC This kind of Interceptor Chain structure can also be interrupted, this kind of interruption is let preHandle The return of  
   *  Back to the value of false when preHandle The return value of false That's when the whole request ends.  
   */ 
  @Override 
  public boolean preHandle(HttpServletRequest request, 
      HttpServletResponse response, Object handler) throws Exception { 
    // TODO Auto-generated method stub 
    return false; 
  } 
   
  /** 
   *  This method will only be in the current one Interceptor the preHandle Method returns a value of true Will be executed when. postHandle It is used for processor interception and its execution time is processed by the processor  
   *  And then, that's where Controller Is executed after the method call to, but it will be executed after DispatcherServlet Execute before rendering the view, which means that in this method you can view ModelAndView To fuck  
   *  Make it. The chain structure of this method is in the opposite direction of normal access, that is, declared first Interceptor Interceptors instead call this method after the call, which follows Struts2 The interceptor inside is going to execute something like,  
   *  just Struts2 The inside of the intercept The method is called manually ActionInvocation the invoke Method, Struts2 In the call ActionInvocation the invoke The method is called under 1 a Interceptor 
   *  Or call action And then you're going to have to Interceptor The contents of the previous call are written in the call invoke Before, before Interceptor The contents of the subsequent call are written in the call invoke After the method.  
   */ 
  @Override 
  public void postHandle(HttpServletRequest request, 
      HttpServletResponse response, Object handler, 
      ModelAndView modelAndView) throws Exception { 
    // TODO Auto-generated method stub 
     
  } 
 
  /** 
   *  This method also requires the current counterpart Interceptor the preHandle The return value of the true Will be executed when. This method will be used after the entire request is completed, i.e DispatcherServlet Rendered view execution,  
   *  The main purpose of this method is to clean up the resources, but this method can only be used at present Interceptor the preHandle The return value of the true Will be executed when.  
   */ 
  @Override 
  public void afterCompletion(HttpServletRequest request, 
      HttpServletResponse response, Object handler, Exception ex) 
  throws Exception { 
    // TODO Auto-generated method stub 
     
  } 
   
} 

(2) implement WebRequestInterceptor interface

There are also three methods defined in WebRequestInterceptor, through which we implement interception. All three methods pass the same parameter, WebRequest, so what is WebRequest? This WebRequest is an interface defined by Spring, and its method definitions are basically the same as HttpServletRequest 1. All operations on WebRequest in WebRequestInterceptor will be synchronized to HttpServletRequest, and then passed directly in the current request 1.

(1) preHandle(WebRequest request) method. This method will be called before the request is processed, which means it will be called before the Controller method call. This method with the preHandle HandlerInterceptor is different, the main difference is that the return value of this method is void, also is not return a value, so we mainly use it for like 1 resource preparations, such as we can when using Hibernate in this method to prepare a Hibernate Session object, and then use WebRequest setAttribute (name value, scope) put it in the WebRequest attributes. Here you can talk about the third parameter of the setAttribute method, scope, which is of type 1 Integer. Three constants are defined for WebRequest in its parent interface, RequestAttributes:

SCOPE_REQUEST: its value is 0, which means that it is only accessible in request.

SCOPE_SESSION: it has a value of 1, which represents a locally isolated session if the environment allows, otherwise represents normal session and is accessible within the session range.

SCOPE_GLOBAL_SESSION: it has a value of 2, which represents a globally Shared session if the environment allows it, otherwise represents normal session and is accessible within the session range.

(2) postHandle(WebRequest request, ModelMap model) method. This method will be called after the request is processed, after the Controller method is called, but before the view returns to be rendered, so you can change the presentation of the data in this method by changing the data model ModelMap. This method has two parameters. The WebRequest object is used to pass the entire request data. For example, the data prepared in preHandle can be passed and accessed through WebRequest. ModelMap is the Model object returned after processing by Controller. We can change the Model model returned by changing its properties.

(3) afterCompletion(WebRequest request, Exception ex) method. This method is executed after the entire request processing is completed, that is, after the view is returned and rendered. So you can release the resource in this method. The WebRequest parameter can then pass the resources we prepared in preHandle here for release. The Exception parameter represents the currently requested exception object, which is null if the exception thrown in Controller has already been handled by Spring's exception handler.

Here is a simple code description:


import org.springframework.ui.ModelMap; 
import org.springframework.web.context.request.WebRequest; 
import org.springframework.web.context.request.WebRequestInterceptor; 
 
public class AllInterceptor implements WebRequestInterceptor { 
   
  /** 
   *  Executed before the request is processed, this method is primarily used to prepare the resource data, which can then be placed as request properties WebRequest In the  
   */ 
  @Override 
  public void preHandle(WebRequest request) throws Exception { 
    // TODO Auto-generated method stub 
    System.out.println("AllInterceptor..............................."); 
    request.setAttribute("request", "request", WebRequest.SCOPE_REQUEST);// This is put request Scoped, so only in the current request request Get to the  
    request.setAttribute("session", "session", WebRequest.SCOPE_SESSION);// This is put session Scoped, it can only be accessed in a locally isolated session if the environment allows, otherwise it can be accessed in a normal current session  
    request.setAttribute("globalSession", "globalSession", WebRequest.SCOPE_GLOBAL_SESSION);// It can be accessed in a globally Shared session if the environment allows, otherwise in a normal current session  
  } 
 
  /** 
   *  The method will be in Controller After execution, before going back to the view, ModelMap Said the request Controller Returned after processing Model Object, so it can be in  
   *  Modify in this method ModelMap To change the returned model.  
   */ 
  @Override 
  public void postHandle(WebRequest request, ModelMap map) throws Exception { 
    // TODO Auto-generated method stub 
    for (String key:map.keySet()) 
      System.out.println(key + "-------------------------");; 
    map.put("name3", "value3"); 
    map.put("name1", "name1"); 
  } 
 
  /** 
   *  This method is called after the entire request is completed, that is, after the view is rendered, and is primarily used to perform 1 The release of some resources  
   */ 
  @Override 
  public void afterCompletion(WebRequest request, Exception exception) 
  throws Exception { 
    // TODO Auto-generated method stub 
    System.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-="); 
  } 
   
} 
 

2. Add the defined interceptor class to SpringMVC's interceptor system

1. Add schema support for MVC to the SpringMVC configuration file


xmlns:mvc="http://www.springframework.org/schema/mvc" 
  xsi:schemaLocation=" http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" 

Here is an example of my declaration:


<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:mvc="http://www.springframework.org/schema/mvc" 
  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"> 

This makes it possible to use the mvc tag in the SpringMVC configuration file, and the mvc tag has an mvc:interceptors that is used to declare the interceptor for SpringMVC.

(2) use the mvc:interceptors tag to declare interceptors that need to be added to the SpringMVC interceptor chain


<mvc:interceptors> 
  <!--  use bean define 1 a Interceptor Is directly defined in mvc:interceptors The root of the following Interceptor All requests will be intercepted  --> 
  <bean class="com.host.app.web.interceptor.AllInterceptor"/> 
  <mvc:interceptor> 
    <mvc:mapping path="/test/number.do"/> 
    <!--  Defined in the mvc:interceptor The following representation is for specific requests to be intercepted  --> 
    <bean class="com.host.app.web.interceptor.LoginInterceptor"/> 
  </mvc:interceptor> 
</mvc:interceptors> 

As you can see from the above example, you can use the mvc:interceptors tag to declare the 1 series of interceptors, and then they can form a chain of interceptors. The order of execution of the interceptors is in the order declared. The preHandle method in the first declared interceptor will be executed first, while its postHandle and afterCompletion methods will be executed afterwards.

There are two main ways to declare interceptor under the mvc:interceptors tag:

(1) directly define an bean object of an Interceptor implementation class. The Interceptor interceptor declared in this way will intercept all requests.

(2) declare using the label mvc:interceptor. An Interceptor declared in this way can define the request path to be intercepted using the mvc:mapping subtag.

After the above two steps, the defined interceptor will take effect to intercept the specific request.


Related articles: