Spring MVC Learning Notes (2) Processor Interceptor Details

Keywords: Spring Session Apache Hibernate

The processor interceptor of Spring Web MVC is similar to the Filter filter Filter in Servlet development, which is used to preprocess and post-process the processor.

Interceptor application scenarios:
1. Logging: Logging requests for information for information monitoring, information statistics, computing PV (Page View), etc.
2. Privilege checking: If login checking, enter the processor to check whether to login or not, if not directly return to the login page;
3. Performance monitoring: Sometimes the system is inexplicably slow at a certain time. It can record the start time before entering the processor by the interceptor and the end time after processing, so as to get the processing time of the request (if there is a reverse proxy, such as apache can record automatically);
4. General Behavior: Read cookie s to get user information and put user objects into requests, so as to facilitate the use of subsequent processes, such as extracting Locale, Theme
Information and so on, as long as it is needed by multiple processors, can be implemented using interceptors.
5. OpenSession InView: Hibernate, for example, opens Session when it enters the processor and closes Session when it is finished.
... The essence is AOP (Aspect-Oriented Programming), which means that all functions that meet cross-cutting concerns can be implemented in interceptors.

Interceptor Interface Source Code
public interface HandlerInterceptor {

    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception;

    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
}

preHandle: Pre-processing callback method to achieve the processor's pre-processing (such as login checking), the third parameter is the response processor;
Return value: true means to continue the process (e.g. call the next interceptor or processor); false means to interrupt the process (e.g. fail login check) and not to continue to call other interceptors or processors. At this time, we need to respond through response;
postHandle: Post-processing callback method that implements post-processing of the processor (but before rendering the view), when we can process model data or view through modelAndView (model and view object), modelAndView may also be null.
After Completion: Callback method after the entire request is processed, that is, when the view is rendered. For example, in performance monitoring, we can record the end time and output the time consumed. We can also clean up some resources, similar to last in try-catch-final, but only call the afterCompletion of the interceptor that preHandle returns true in the processor execution chain.

Sometimes we just need to implement one of the three callback methods. If we implement the Handler Interceptor interface, whether you need it or not, the three methods must be implemented. So spring provides a Handler Interceptor Adapter adapter (an implementation of an adapter design pattern), which allows us to implement only the callback methods we need.

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

/**
     * This implementation always returns {@code true}.
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        return true;
    }

    /**
     * This implementation is empty.
     */
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }

    /**
     * This implementation is empty.
     */
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }

    /**
     * This implementation is empty.
     */
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }

}

Here's a demo of the interceptor.

1. First define three different interceptors
Handler Interceptor 1 Interceptor

    public class HandlerInterceptor1 extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("===========HandlerInterceptor1 preHandle");

        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){
        System.out.println("===========HandlerInterceptor1 postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){
        System.out.println("===========HandlerInterceptor1 afterCompletion");
    }
 }

Handler Interceptor 2 Interceptor

    public class HandlerInterceptor2 extends HandlerInterceptorAdapter {
    //Here you can generally inherit the Handler Interceptor Adapter adapter
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("===========HandlerInterceptor2 preHandle");

        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){
        System.out.println("===========HandlerInterceptor2 postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){
        System.out.println("===========HandlerInterceptor2 afterCompletion");
    }
}

Handler Interceptor 3 Interceptor

    public class HandlerInterceptor3 extends HandlerInterceptorAdapter {
    //Here you can generally inherit the Handler Interceptor Adapter adapter
    @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("===========HandlerInterceptor3 preHandle");

        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){
        System.out.println("===========HandlerInterceptor3 postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){
        System.out.println("===========HandlerInterceptor3 afterCompletion");
    }
}

2. Add the following configuration in spring-servlet.xml:

 <mvc:interceptors>
    <bean id="handlerInterceptor1"
          class="com.spring.interceptor.HandlerInterceptor1"/>
    <bean id="handlerInterceptor2"
          class="com.spring.interceptor.HandlerInterceptor2"/>
    <mvc:interceptor>
        <mvc:mapping path="/view"/>
        <bean id="handlerInterceptor3"
              class="com.spring.interceptor.HandlerInterceptor3"/>
    </mvc:interceptor>
</mvc:interceptors>

The execution order of the interceptor:
The preHandle method is executed in the configuration order in the above configuration file
The postHandle and afterCompletion methods are executed in reverse order in the above order

Use the < mvc: interceptor > tag to configure the interceptor and add path configurations such as "/ view" to set the request path that needs to be intercepted; the default < bean > tag configures the interceptor to intercept all requests.

So far: The interceptor has been configured and the console output of requesting non/view path and/view path requests is as follows:

===========HandlerInterceptor1 preHandle
===========HandlerInterceptor2 preHandle
===========HandlerInterceptor2 postHandle
===========HandlerInterceptor1 postHandle
===========HandlerInterceptor2 afterCompletion
===========HandlerInterceptor1 afterCompletion

***********************************************************************************

===========HandlerInterceptor1 preHandle
===========HandlerInterceptor2 preHandle
===========HandlerInterceptor3 preHandle
===========HandlerInterceptor3 postHandle
===========HandlerInterceptor2 postHandle
===========HandlerInterceptor1 postHandle
===========HandlerInterceptor3 afterCompletion
===========HandlerInterceptor2 afterCompletion
===========HandlerInterceptor1 afterCompletion

Posted by subhuman on Thu, 28 Mar 2019 07:21:28 -0700