springmvc的拦截器
springmvc执行流程
● 客户端(浏览器)发送请求,直接请求到 DispatcherServlet .
● mvc中是否存在对应的映射,存在交给HandlerMapping返回HandlerExecutionChain对象
● 不存在查看是否配置了<mvc:default_servlet-handler>
配置了,将请求交给tomcat,由tomcat按照静态资源进行查找
● 如果没有配置,直接返回404
● 根据HandlerExecutionChain对象获取请求拦截器的preHandle方法来得到HandleAdapter实现类对象.
● 由适配器对象来执行目标方法并返回ModelAndView对象,适配其 将其返回给DispatcherServlet
● DispatcherServlet委托给视图解析器从ModelAndView对象中解析出View对象
● 由DispatcheServlet委托给具体视图,由视图进行渲染视图的操作,并响应给客户端.
● 最终DispatcherServlet调用拦截器的进行处理
- springmvc可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口或者可以继承HandlerInterceptorAdapter(对HandlerInterceptor使用接口适配器)后的抽象类,对接口的方法做了一个空实现.继承该类可以有选择的实现这三个抽象方法.
HandlerInterceptor
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 默认为true,即默认执行postHandler
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
- preHandler:这个方法在业务处理器处理请求之前被调用,在该方法中用户请求的request进行处理,如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器或是业务处理器取进行处理,返回true,否则返回false.
- postHandler:在业务处理器处理完请求后,但是DispatcherServlet向客户端返回响应数据前被调用,在该方法中对用户请求的request进行处理.
- afterCompletion:这个方法在DispatcherServlet完成处理请求后被调用,一般在该方法中进行一些资源处理操作.
DispatcherServlet源码
- 在DispatcherServlet中的doDispatcher方法中
单个拦截器执行顺序
- 通过preHandler方法决定是否执行目标方法及后置拦截器
- 返回true就执行目标方法及后置处理器最后执行afterCompletion
- 否则直接执行afterCompletion方法
image.png
多个拦截器执行顺序
- 按照执行preHandler的倒叙执行顺序执行postHandler和afterCompletion.
- 当我们发送请求到DispatcherServlet,会根据请求映射器,返回一个执行器链对象,该对象中包含了若干个请求拦截器对象(RequestIntecept数组类型)对象.
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 获取请求拦截器
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历,记录preHandler返回true的下标个数
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
// 执行AfterCompletion
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
- 出现错误后不执行拦截器的postHandler和目标方法.
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 倒叙遍历
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
}
小结
- preHandler执行,afterCompletion一定执行.
- preHandler返回false,该拦截器的postHandler的目标方法一定不执行