单个拦截器的执行流程
在运行程序时,拦截器的执行是有一定顺序的,该顺序与配置文件中所定义的拦截器的顺序相关。如果在项目中只定义了一个拦截器,那么该拦截器在程序中的执行流程如图1所示。
图1 单个拦截器的执行流程
从图1可以看出,程序首先会执行拦截器类中的preHandle()方法,如果该方法的返回值为true,则程序会继续向下执行处理器中的方法,否则将不再向下执行;在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应;在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。
为了验证上面所讲解的拦截器执行流程,下面通过一个案例来演示其使用,具体步骤如下。
(1)在Eclipse中,创建一个名为chapter15的Web项目,将Spring MVC程序运行所需JAR包复制到项目的lib目录中,并发布到类路径下。
(2)在web.xml中,配置Spring MVC的前端过滤器和初始化加载配置文件等信息。
(3)在src目录下,创建一个com.itheima.controller包,并在包中创建控制器类HelloController,编辑后的代码如文件1所示。
文件1 HelloController.java
1 package com.itheima.controller;
2 import org.springframework.stereotype.Controller;
3 import org.springframework.web.bind.annotation.RequestMapping;
4 @Controller
5 public class HelloController {
6 /**
7 * 页面跳转
8 */
9 @RequestMapping("/hello")
10 public String Hello() {
11 System.out.println("Hello!");
12 return "success";
13 }
14 }
(4)在src目录下,创建一个com.itheima.interceptor包,并在包中创建拦截器类CustomInterceptor。该类需要实现HandlerInterceptor接口,并且在实现方法中需要编写输出语句来输出信息,如文件2所示。
文件2 CustomInterceptor.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 * 实现了HandlerInterceptor接口的自定义拦截器类
8 */
9 public class CustomInterceptor implements HandlerInterceptor{
10 @Override
11 public boolean preHandle(HttpServletRequest request,
12 HttpServletResponse response, Object handler)throws Exception {
13 System.out.println("CustomInterceptor...preHandle");
14 //对拦截的请求进行放行处理
15 return true;
16 }
17 @Override
18 public void postHandle(HttpServletRequest request,
19 HttpServletResponse response, Object handler,
20 ModelAndView modelAndView) throws Exception {
21 System.out.println("CustomInterceptor...postHandle");
22 }
23 @Override
24 public void afterCompletion(HttpServletRequest request,
25 HttpServletResponse response, Object handler,
26 Exception ex) throws Exception {
27 System.out.println("CustomInterceptor...afterCompletion");
28 }
29 }
(5)在src目录下,创建并配置Spring MVC的配置文件,如文件3所示。
文件3 springmvc-config.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:mvc="http://www.springframework.org/schema/mvc"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
8 http://www.springframework.org/schema/mvc
9 http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
10 http://www.springframework.org/schema/context
11 http://www.springframework.org/schema/context/spring-context-4.3.xsd">
12 <!-- 定义组件扫描器,指定需要扫描的包 -->
13 <context:component-scan base-package="com.itheima.controller" />
14 <!-- 定义视图解析器 -->
15 <bean id="viewResolver" class=
16 "org.springframework.web.servlet.view.InternalResourceViewResolver">
17 <!-- 设置前缀 -->
18 <property name="prefix" value="/WEB-INF/jsp/" />
19 <!-- 设置后缀 -->
20 <property name="suffix" value=".jsp" />
21 </bean>
22 <!-- 配置拦截器 -->
23 <mvc:interceptors>
24 <!--使用bean直接定义在<mvc:interceptors>下面的拦截器将拦截所有请求-->
25 <bean class="com.itheima.interceptor.CustomInterceptor"/>
26 </mvc:interceptors>
27 </beans>
由于配置拦截器使用的是<mvc:interceptors>元素,所以需要配置mvc的schema信息。本案例演示的是单个拦截器的执行顺序,所以这里只配置了一个全局的拦截器。
(6)在WEB-INF目录下,创建一个jsp文件夹,并在该文件夹中创建一个页面文件success.jsp,然后在页面文件的<body>元素内编写任意显示信息,如“ok”。
(7)将项目发布到Tomcat服务器并启动,在浏览器中访问地址http://localhost:8080/chapter15**/**hello,程序正确执行后,浏览器会跳转到success.jsp页面,此时控制台的输出结果如图2所示。
图2 运行结果
从图2可以看出,程序先执行了拦截器类中的preHandle()方法,然后执行了控制器中的Hello()方法,最后分别执行了拦截器类中的postHandle()方法和afterCompletion()方法。这与上文所描述的单个拦截器的执行顺序是一致的。