创建多个拦截器,理解其执行过程。
创建三个拦截器类:
每个拦截器类都有三个方法:
preHandle:在业务处理器处理请求之前被调用
postHandle:在业务处理器处理请求执行完成后,生成视图之前执行的动作 可在modelAndView中加入数据
afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
IndexInterceptor.java
1 package interceptor; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 import org.springframework.web.servlet.HandlerInterceptor; 10 11 public class IndexInterceptor implements HandlerInterceptor { 12 /** 13 * 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 14 * 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链, 15 * 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion() 16 */ 17 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 18 System.out.println("preHandle(),在访问Controller之前被调用"); 19 return true; 20 } 21 22 /** 23 * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 可在modelAndView中加入数据,比如当前时间 24 */ 25 @Override 26 public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, 27 org.springframework.web.servlet.ModelAndView arg3) throws Exception { 28 // TODO Auto-generated method stub 29 Calendar calendar = Calendar.getInstance(); 30 String dateString = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(calendar.getTime()); 31 System.out.println("postHandle(), 在访问Controller之后,访问视图之前被调用,这里可以注入一个时间到modelAndView中,用于后续视图显示"); 32 arg3.addObject("date", "由拦截器1生成的时间:" + dateString); 33 } 34 35 /** 36 * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 37 * 38 * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() 39 */ 40 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 41 throws Exception { 42 System.out.println("afterCompletion(), 在访问视图之后被调用"); 43 } 44 45 }
IndexInterceptor2.java(年份加1)
1 package interceptor; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 import org.springframework.web.servlet.HandlerInterceptor; 10 11 public class IndexInterceptor2 implements HandlerInterceptor { 12 /** 13 * 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 14 * 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链, 15 * 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion() 16 */ 17 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 18 System.out.println("preHandle()2,在访问Controller之前被调用"); 19 return true; 20 } 21 22 /** 23 * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 可在modelAndView中加入数据,比如当前时间 24 */ 25 @Override 26 public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, 27 org.springframework.web.servlet.ModelAndView arg3) throws Exception { 28 // TODO Auto-generated method stub 29 Calendar calendar = Calendar.getInstance(); 30 int year = calendar.get(calendar.YEAR); 31 int month = calendar.get(calendar.MONTH); 32 int day = calendar.get(calendar.DAY_OF_MONTH); 33 int hour = calendar.get(calendar.HOUR); 34 int minute = calendar.get(calendar.MINUTE); 35 int second = calendar.get(calendar.SECOND); 36 calendar.set(year + 1, month, day, hour, minute, second); 37 String dateString = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(calendar.getTime()); 38 System.out.println("postHandle()2, 在访问Controller之后,访问视图之前被调用,这里可以注入一个时间到modelAndView中,用于后续视图显示"); 39 arg3.addObject("date2", "由拦截器2生成的时间:" + dateString); 40 } 41 42 /** 43 * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 44 * 45 * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() 46 */ 47 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 48 throws Exception { 49 System.out.println("afterCompletion()2, 在访问视图之后被调用"); 50 } 51 52 }
IndexInterceptor3.java(年份加2)
1 package interceptor; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 import org.springframework.web.servlet.HandlerInterceptor; 10 11 public class IndexInterceptor3 implements HandlerInterceptor { 12 /** 13 * 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 14 * 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链, 15 * 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion() 16 */ 17 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 18 System.out.println("preHandle()3,在访问Controller之前被调用"); 19 return true; 20 } 21 22 /** 23 * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 可在modelAndView中加入数据,比如当前时间 24 */ 25 @Override 26 public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, 27 org.springframework.web.servlet.ModelAndView arg3) throws Exception { 28 // TODO Auto-generated method stub 29 Calendar calendar = Calendar.getInstance(); 30 int year = calendar.get(calendar.YEAR); 31 int month = calendar.get(calendar.MONTH); 32 int day = calendar.get(calendar.DAY_OF_MONTH); 33 int hour = calendar.get(calendar.HOUR); 34 int minute = calendar.get(calendar.MINUTE); 35 int second = calendar.get(calendar.SECOND); 36 calendar.set(year + 2, month, day, hour, minute, second); 37 String dateString = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(calendar.getTime()); 38 System.out.println("postHandle()3, 在访问Controller之后,访问视图之前被调用,这里可以注入一个时间到modelAndView中,用于后续视图显示"); 39 arg3.addObject("date3", "由拦截器3生成的时间:" + dateString); 40 } 41 42 /** 43 * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 44 * 45 * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() 46 */ 47 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 48 throws Exception { 49 System.out.println("afterCompletion()3, 在访问视图之后被调用"); 50 } 51 52 }
配置文件myspringmvc-servlet.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:mvc="http://www.springframework.org/schema/mvc" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.0.xsd 9 http://www.springframework.org/schema/mvc 10 http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 11 "> 12 <bean id="viewResolver" 13 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 14 <property name="prefix" value="/WEB-INF/page/" /> 15 <property name="suffix" value=".jsp" /> 16 </bean> 17 18 <bean id="simpleUrlHandlerMapping" 19 class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 20 <property name="mappings"> 21 <props> 22 <prop key="/index">indexController</prop> 23 </props> 24 </property> 25 </bean> 26 <bean id="indexController" class="controller.IndexController"></bean> 27 <!-- 拦截器1 --> 28 <mvc:interceptors> 29 <mvc:interceptor> 30 <mvc:mapping path="/index" /> 31 <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --> 32 <bean class="interceptor.IndexInterceptor" /> 33 </mvc:interceptor> 34 <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 --> 35 </mvc:interceptors> 36 <!-- 拦截器2 --> 37 <mvc:interceptors> 38 <mvc:interceptor> 39 <mvc:mapping path="/index" /> 40 <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --> 41 <bean class="interceptor.IndexInterceptor2" /> 42 </mvc:interceptor> 43 <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 --> 44 </mvc:interceptors> 45 <!-- 拦截器3 --> 46 <mvc:interceptors> 47 <mvc:interceptor> 48 <mvc:mapping path="/index" /> 49 <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --> 50 <bean class="interceptor.IndexInterceptor3" /> 51 </mvc:interceptor> 52 <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 --> 53 </mvc:interceptors> 54 </beans>
情况一:
preHandle在业务处理器处理请求之前被调用,如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller(即主业务) 然后进入拦截器链,从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion()
设置三个拦截器的preHandle函数返回值都为true.。测试结果为:
当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法
情况二:
preHandle在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链,不执行本拦截器中的afterCompletion()
设置第三个拦截器中preHandle函数的返回值为false,其他为true。测试结果:
设置第二个拦截器中preHandle函数的返回值为false,其他为true。测试结果:
情况三:
当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
在第三个拦截器中的postHandle方法中添加一句System.out.println(2 / 0);
测试结果:第三个拦截器中的afterCompletion会执行
在第三个拦截器中的方法中添加一句System.out.println(2 / 0);
1 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 2 throws Exception { 3 System.out.println(2 / 0); 4 System.out.println("afterCompletion()3, 在访问视图之后被调用"); 5 }
必须放在输出语句前
测试结果:拦截器3中的afterCompletion方法就不会执行