Spring MVC多个拦截器执行顺序

为了对比多个拦截器的执行顺序,先创建两个拦截器打比方

第一个拦截器:

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 目标方法执行之前执行
     *
     * @return true不拦截,如果为false,那么后面一连串方法都不会执行(Controller。postHandle。afterCompletion。。等等)
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle1.....");
            return true;
    }

    /**
     * 在目标执行之后 视图返回之前执行
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle1.....");
    }

    /**
     * 在整个流程都执行完毕后执行,记录日志、异常等(用的不多)
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion1.....");
    }
}

第二个拦截器:

public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 目标方法执行之前执行
     *
     * @return true不拦截,如果为false,那么后面一连串方法都不会执行(Controller。postHandle。afterCompletion。。等等)
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2.....");
        return true;
    }

    /**
     * 在目标执行之后 视图返回之前执行
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2.....");
    }

    /**
     * 在整个流程都执行完毕后执行,记录日志、异常等(用的不多)
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion2.....");
    }
}

Spring MVC配置文件中配置拦截器:先配置拦截器1,再配置拦截器2

<!--    配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--            拦截路径,对哪些资源执行拦截操作  /**代表对所有都拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.interceptor.MyInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--            拦截路径,对哪些资源执行拦截操作  /**代表对所有都拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--配置拦截器-->

启动Tomcat服务并访问相应资源,运行结果:

 调换SpringMVC配置文件拦截器的顺序:先配置拦截器2,再配置拦截器1

<!--    配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--            拦截路径,对哪些资源执行拦截操作  /**代表对所有都拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--            拦截路径,对哪些资源执行拦截操作  /**代表对所有都拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--配置拦截器-->

再次运行Tomcat服务执行结果:

preHandle2.....
preHandle1.....
postHandle1.....
postHandle2.....
afterCompletion1.....
afterCompletion2.....

多个拦截器执行preHandle的顺序与Spring MVC配置文件中的配置顺序有关,将配置文件还原到拦截器1~拦截器2

<!--    配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--            拦截路径,对哪些资源执行拦截操作  /**代表对所有都拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.interceptor.MyInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--            拦截路径,对哪些资源执行拦截操作  /**代表对所有都拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--配置拦截器-->

当第一个拦截器的preHandle方法返回true时,才会继续向下调用下一个拦截器的preHandle

修改一下代码,将第一个拦截器的preHandle方法改成false,试着运行程序,看看拦截器2的preHandle是否执行:

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 目标方法执行之前执行
     *
     * @return true不拦截,如果为false,那么后面一连串方法都不会执行(Controller。postHandle。afterCompletion。。等等)
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle1.....");
            return false;
    }

    /**
     * 在目标执行之后 视图返回之前执行
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle1.....");
    }

    /**
     * 在整个流程都执行完毕后执行,记录日志、异常等(用的不多)
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion1.....");
    }
}

执行结果:

只有preHandle1被执行 ,说明拦截器1的preHandle返回false拦截器2压根就不会执行,甚至拦截器1的postHandle和afterCompletion也不会执行

Spring MVC拦截器是一种可插拔的组件,它可以在请求到达控制器之前或者返回视图之前对请求进行处理。Spring MVC 支持单个拦截器或者多个拦截器,下面分别介绍它们的工作流程。 1. 单个拦截器的工作流程 单个拦截器的工作流程如下: - 当一个请求到达 DispatcherServlet 时,DispatcherServlet 会创建一个 HandlerExecutionChain 对象,该对象包含了一个或多个处理器拦截器和一个处理器(即控制器)。 - 在执行处理器之前,DispatcherServlet 会调用拦截器的 preHandle 方法,如果该方法返回 true,则继续执行下一个拦截器或者执行处理器。 - 在执行完处理器之后,DispatcherServlet 会调用拦截器的 postHandle 方法,该方法可以修改 ModelAndView 对象,但不能改变视图。 - 当视图渲染完成后,DispatcherServlet 会调用拦截器的 afterCompletion 方法,该方法可以进行一些资源清理操作。 2. 多个拦截器的工作流程 多个拦截器的工作流程类似于单个拦截器的工作流程,只是多了一些拦截器的调用。 - 当一个请求到达 DispatcherServlet 时,DispatcherServlet 会创建一个 HandlerExecutionChain 对象,该对象包含了多个处理器拦截器和一个处理器(即控制器)。 - 在执行处理器之前,DispatcherServlet 会按照拦截器的声明顺序调用每个拦截器的 preHandle 方法,如果有任何一个拦截器的 preHandle 方法返回 false,则停止拦截器的执行,并返回错误视图。 - 在执行完处理器之后,DispatcherServlet 会按照拦截器的声明顺序倒序调用每个拦截器的 postHandle 方法,该方法可以修改 ModelAndView 对象,但不能改变视图。 - 当视图渲染完成后,DispatcherServlet 会按照拦截器的声明顺序倒序调用每个拦截器的 afterCompletion 方法,该方法可以进行一些资源清理操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

服务端相声演员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值