Spring Web MVC of Spring Family Bucket (7) - Interceptor

Get into the habit of writing together! This is the 11th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

1. Interceptor

Spring MVC provides an interceptor mechanism that allows some interception work before running the target method, or some other processing after the target method runs

The interceptor in Spring MVC is the HandlerInterceptor interface, which contains three methods

image.png

  • preHandler: This method is called before the business processor processes the request. In this method, the user request is processed. If the interceptor is required to intercept the request, other interceptors will be called, or the business processor will be processed. Then return True to release the request, and return false if no need to call other components, neither to release the request
  • postHandler: This method is called after the business processor has finished processing the request, but it is called before the DispatcherServlet returns a response to the client. In this method, the user request request is processed
  • afterCompletion: This method is called after the DispatcherServlet has completely processed the request, and some resource cleanup operations can be performed in this method

Second, the custom interceptor

Copy the spring-mvc-ajax project, rename it to spring-mvc-handler, and delete the classes and files except the configuration.

The normal flow of the interceptor

Create a new HandlerInterceptorSamplerController, define the interceptor method in the Controller, test the custom interceptor, and return to the success page

@Controller
public class HandlerInterceptorSamplerController {

    @RequestMapping("/interceptor")
    public String interceptor(){

        System.out.println("interceptor方法被调用");
        return "success";
    }
}
复制代码

Add a hyperlink to the index.jsp page

<a href="/interceptor">拦截该请求</a>
复制代码

Add the interceptor package, create a new custom interceptor ZuluInterceptor, the custom interceptor must implement the HandlerInterceptor interface, and add log printing to each method in the interceptor

public class ZuluInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println(this.getClass().getName() + " preHandler方法运行了");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(this.getClass().getName() + " postHandle方法运行了");
        System.out.println(modelAndView.getViewName());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(this.getClass().getName() + " afterCompletion方法运行了");
    }
}
复制代码

Register the interceptor in the Spring MVC configuration file and configure which requests the interceptor intercepts

<mvc:interceptors>
    <!--第一种方式配置某个拦截器,默认是拦截所有请求的-->
    <bean class="com.citi.interceptor.ZuluInterceptor"></bean>
</mvc:interceptors>
复制代码

Start the app and click the hyperlink on the home page

image.pngAccording to the console output, the custom interceptor is called successfully

因此拦截器的正常流程是:拦截器preHandler方法 -> 目标方法 -> 拦截器的postHandler方法 -> 页面渲染 -> 拦截器的afterCompletion方法

拦截器的异常流程

异常流程1 - preHandler返回false

在ZuluInterceptor拦截器的preHandler方法返回false,再次启动,点击首页的超链接 image.png 控制台只输出了preHandler方法的执行信息,因此只要preHandler返回false,既不放行就不会有以后的方法的执行。

异常流程2 - 其他异常

保持preHandler方法返回true,同时在Controller中的interceptor方法返回页面前增加异常代码

@RequestMapping("/interceptor")
public String interceptor(){

    System.out.println("interceptor方法被调用");
    // 异常代码
    int i = 10 / 0;
    return "success";
}
复制代码

再次重新启动应用,点击页面的超链接 image.png 页面出现有异常代码导致的报错

image.png 此时控制台执行了afterCompletion方法

三、多个拦截器执行顺序

在interceptor包中拷贝ZuluInterceptor并重命名为DeltaInterceptor;在Spring MVC配置文件中注册新定义的拦截器

<mvc:interceptors>
    <!--第一种方式配置某个拦截器,默认是拦截所有请求的-->
    <bean class="com.citi.interceptor.ZuluInterceptor"></bean>
    <bean class="com.citi.interceptor.DeltaInterceptor"></bean>
</mvc:interceptors>
复制代码

将Controller中的interceptor方法中的异常代码注销,重新启动,点击页面的插连接

image.png 根据控制台的输出可以确定,限制性了Zulu拦截器中的preHandler方法,接着执行Delta拦截器的preHandler方法,再执行目标方法,接着调用Delta拦截器的postHandler,再执行Zulu拦截器的postHandler,再执行Delta拦截器的afterCompletion方法,最后再执行Zulu拦截器的afterCompletion方法

拦截顺序: 拦截器拦截顺序是按照配置的先后顺序,调整拦截器配置顺序

<mvc:interceptors>
    <!--第一种方式配置某个拦截器,默认是拦截所有请求的-->
    <bean class="com.citi.interceptor.DeltaInterceptor"></bean>
    <bean class="com.citi.interceptor.ZuluInterceptor"></bean>
</mvc:interceptors>
复制代码

Start again and click the hyperlink on the home page. image.pngAccording to the console output, the Delta interceptor configured first in the configuration file is executed first.

Exception flow of multiple interceptors:

Keep the Delta interceptor first and Zulu interceptor last in the Spring MVC configuration file. If the Delta interceptor is not released, there will be no subsequent calls; if the Zulu interceptor is not released, what will be the result?

Return false in the Zulu interceptor, restart the app, and click the hyperlink to the home page

image.pngAccording to the output of the console, it can be determined that the Zulu interceptor will not be released, but the afterCompletion method of Delta will still be executed.

已放行了的拦截器的afterCompletion方法总会执行

Guess you like

Origin juejin.im/post/7085374517136064542