10--拦截器
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
实现HandlerInterceptor接口,如下:
public class HandlerInterceptor1 implements HandlerInterceptor { // 进入 Handler方法之前执行 // 用于身份认证、身份授权 // 比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("HandlerInterceptor1...preHandle"); // return false表示拦截,不向下执行 // return true表示放行 return true; } // 进入Handler方法之后,返回modelAndView之前执行 // 应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("HandlerInterceptor1...postHandle"); } // 执行Handler完成执行此方法 // 应用场景:统一异常处理,统一日志处理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("HandlerInterceptor1...afterCompletion"); } }
public class HandlerInterceptor2 implements HandlerInterceptor { // 进入 Handler方法之前执行 // 用于身份认证、身份授权 // 比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("HandlerInterceptor2...preHandle"); // return false表示拦截,不向下执行 // return true表示放行 return true; } // 进入Handler方法之后,返回modelAndView之前执行 // 应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("HandlerInterceptor2...postHandle"); } // 执行Handler完成执行此方法 // 应用场景:统一异常处理,统一日志处理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("HandlerInterceptor2...afterCompletion"); } }
9.1 拦截器配置
1.1 针对某种mapping配置拦截器(不推荐使用)
springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="handlerInterceptor1"/> <ref bean="handlerInterceptor2"/> </list> </property> </bean> <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/> <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
2.1 针对所有mapping配置全局拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
springmvc.xml中
<!--拦截器 --> <mvc:interceptors> <!--多个拦截器,顺序执行 --> <!-- 登陆认证拦截器 --> <!-- /**表示所有url包括子url路径 --> <mvc:mapping path="/**"/> <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
9.2 拦截测试
9.2.1 两个拦截器都放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
总结:preHandle方法按顺序执行,postHandle和afterCompletion按拦截器配置的逆向顺序执行。
9.2.2 拦截器1放行,拦截器2不放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
总结:
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行。
9.2.3 拦截器1不放行,拦截器2不放行
HandlerInterceptor1...preHandle
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。
9.3 小结
根据测试结果,对拦截器应用。
比如:统一日志处理拦截器,需要该 拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)