过滤器—>DispatcherServlet---->Controller方法
拦截器对Controller方法 进行拦截
filter是servlet之前拦截,interceptor是触发请求方法拦截
拦截器中的3个抽象方法
控制器方法,也叫处理器方法,Handerle
preHanderle 就是在控制器方法前执行
postHanderle控制器方法后执行
afterComplerion 渲染视图后执行
使用案例
//extends HandlerInterceptorAdapter 也可以 官方说过时了
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor--->preHandle");
//HandlerInterceptor.super.preHandle(request, response, handler) 默认的这个应该是true;
//返回f 是拦截
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor--->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor--->afterCompletion");
}
}
2
@Component
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor--->preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("SecondInterceptor--->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("SecondInterceptor--->afterCompletion");
}
}
2.配置(注册)拦截器
方法一:
<mvc:interceptors>
<!--当前的拦截器就配置完成了-->
<bean class="com.dong.mvc.Interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
方法二:扫描这个bean,然后在类上加上@Component,然后再写下面的配置。
<mvc:interceptors>
<!--当前的拦截器就配置完成了-->
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
- 方法一和二会对所有的前端控制器处理的请求进行拦截
方法三:
这个就可以自定义拦截的访问路径
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/"/>
<!-- 当前拦截所有前端控制器处理的请求 除了主页面/ -->
<bean class="com.dong.mvc.Interceptor.FirstInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<mvc:mapping path="/*"/> 这个/* 表示拦截web目录下一层的请求,不会拦截访问下下层的请求,/** 才是所有的请求
和dispatcherServlet里的规则不一样
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor--->preHandle");
//HandlerInterceptor.super.preHandle(request, response, handler) 默认的这个应该是true;
//返回f 是拦截
return true;
}
多个时的执行顺序
两个拦截器时:
<bean class="com.dong.mvc.Interceptor.FirstInterceptor"></bean>
<bean class="com.dong.mvc.Interceptor.SecondInterceptor"></bean>
顺序:输出结果:
FirstInterceptor—>preHandle
SecondInterceptor—>preHandle
SecondInterceptor—>postHandle
FirstInterceptor—>postHandle
SecondInterceptor—>afterCompletion
FirstInterceptor—>afterCompletion
-
preHandle:配置的顺序
-
afterCompletion,postHandle:配置的反序
源码分析:
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
interceptorList是根据配置文件中的顺序加进去的拦截器
所以PreHandle这里是顺序执行的
interceptorindex可以理解为最后一个成功的拦截器
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
i-- 反序执行的postHandle
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
interceptorIndex 代表的是interceptor的preHandle返回true的最后一个
也就是 已经放行了的拦截器会执行afterCompletion,而applyPostHandle是不管放行了没有都会执行的
通过第一段的源码 我们应该发现 一旦有一个拦截后所有的PostHandle都不执行,而afterCompletion会执行前面已经放行了的对应的afterCompletion