多个拦截器的执行流程
在大型的企业级项目中,通常不会只有一个拦截器,开发人员可能会定义很多拦截器来实现不同的功能。那么多个拦截器的执行顺序又是怎样的呢?下面通过一张图来描述多个拦截器的执行流程(假设有两个拦截器Interceptor1和Interceptor2,并且在配置文件中, Interceptor1拦截器配置在前),如图1所示。
图1 多个拦截器的执行流程
从图1可以看出,当有多个拦截器同时工作时,它们的preHandle()方法会按照配置文件中拦截器的配置顺序执行,而它们的postHandle()方法和afterCompletion()方法则会按照配置顺序的反序执行。
为了验证上述描述,下面通过修改15.2.1小节的案例来演示多个拦截器的执行,具体步骤如下。
(1)在com.itheima.interceptor包中,创建两个拦截器类Interceptor1和Interceptor2,这两个拦截器类均继承自HandlerInterceptor,并重写其中的方法,如文件1和文件1所示。
文件1 Interceptor1.java
1 package com.itheima.interceptor;
2 import javax.servlet.http.HttpServletRequest;
3 import javax.servlet.http.HttpServletResponse;
4 import org.springframework.web.servlet.HandlerInterceptor;
5 import org.springframework.web.servlet.ModelAndView;
6 /**
7 * 以实现接口的方式定义拦截器
8 */
9 public class Interceptor1 implements HandlerInterceptor {
10 @Override
11 public boolean preHandle(HttpServletRequest request,
12 HttpServletResponse response, Object handler) throws Exception {
13 System.out.println("Intercepter1...preHandle");
14 return true;
15 }
16 @Override
17 public void postHandle(HttpServletRequest request,
18 HttpServletResponse response, Object handler,
19 ModelAndView modelAndView) throws Exception {
20 System.out.println("Intercepter1...postHandle");
21 }
22 @Override
23 public void afterCompletion(HttpServletRequest request,
24 HttpServletResponse response, Object handler,
25 Exception ex) throws Exception {
26 System.out.println("Intercepter1...afterCompletion");
27 }
28 }
文件2 Interceptor2.java
1 package com.itheima.interceptor;
2 import javax.servlet.http.HttpServletRequest;
3 import javax.servlet.http.HttpServletResponse;
4 import org.springframework.web.servlet.HandlerInterceptor;
5 import org.springframework.web.servlet.ModelAndView;
6 /**
7 * 以实现接口的方式定义拦截器
8 */
9 public class Interceptor2 implements HandlerInterceptor{
10 @Override
11 public boolean preHandle(HttpServletRequest request,
12 HttpServletResponse response, Object handler) throws Exception {
13 System.out.println("Interceptor2...preHandle");
14 return true;
15 }
16 @Override
17 public void postHandle(HttpServletRequest request,
18 HttpServletResponse response, Object handler,
19 ModelAndView modelAndView) throws Exception {
20 System.out.println("intercepter2...postHandle");
21 }
22 @Override
23 public void afterCompletion(HttpServletRequest request,
24 HttpServletResponse response, Object handler, Exception ex)
25 throws Exception {
26 System.out.println("Intercepter2...afterCompletion");
27 }
28 }
(2)在配置文件springmvc-config.xml中的<mvc:interceptors>元素内配置上面所定义的两个拦截器,配置代码如下所示。
<!-- 拦截器1 -->
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/**" />
<!-- 定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截的 -->
<bean class="com.itheima.interceptor.Interceptor1" />
</mvc:interceptor>
<!-- 拦截器2 -->
<mvc:interceptor>
<mvc:mapping path="/hello" />
<bean class="com.itheima.interceptor.Interceptor2" />
</mvc:interceptor>
在上述拦截器的配置代码中,第一个拦截器会作用于所有路径下的请求,而第二个拦截器会作用于以“/hello”结尾的请求。
小提示:
为了不影响程序的输出结果,可将上一小节案例中所配置的CustomInterceptor的拦截器配置注释掉。
(3)发布项目到Tomcat服务器并启动,在浏览器中访问地址http://localhost:8080/chapter15/hello,控制台中输出的信息如图2所示。
图2 运行结果
从图2可以看出,程序先执行了前两个拦截器类中的preHandle()方法,这两个方法的执行顺序与配置文件中定义的顺序相同;然后执行了控制器类中的Hello()方法;最后执行了两个拦截器类中的postHandle()方法和afterCompletion()方法,且这两个方法的执行顺序与配置文件中所定义的拦截器顺序相反。