歡迎光臨我的博客[http://poetize.cn],前端使用Vue2,聊天室使用Vue3,后臺(tái)使用Spring Boot
前言
SpringMVC 攔截器也是Aop(面向切面)思想構(gòu)建,但不是 Spring Aop 動(dòng)態(tài)代理實(shí)現(xiàn)的,
主要采用責(zé)任鏈和適配器的設(shè)計(jì)模式來實(shí)現(xiàn),直接嵌入到 SpringMVC 入口代碼里面。
流程分析
瀏覽器請(qǐng)求
DispatcherServlet 執(zhí)行調(diào)用 doService(request, response) 作為 Servlet 主要執(zhí)行者,
doService(request, response) 通過調(diào)用 doDispatch(request, response) 來真正執(zhí)行請(qǐng)求處理
doDispatch(request, response) 中完成攔截器的添加和攔截器攔截處理
通過 getHandler(HttpServletRequest request) 獲取到 HandlerExecutionChain 處理器執(zhí)行鏈,
將攔截器注入到 HandlerExecutionChain 的屬性中。
分別調(diào)用 HandlerExecutionChain 的三個(gè)方法,applyPreHandle、applyPostHandle、triggerAfterCompletion,
實(shí)現(xiàn)前置攔截/請(qǐng)求提交攔截和請(qǐng)求完成后攔截。
使用責(zé)任鏈的設(shè)計(jì)模式,實(shí)際調(diào)用的是HandleInterceptor的三個(gè)接口,分別對(duì)應(yīng)preHandle、postHandle、afterCompletion
HandlerExecutionChain 源碼分析
public class HandlerExecutionChain {
private final Object handler;
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
private int interceptorIndex;
/**
按照列表中interceptor的順序來執(zhí)行它們的preHandle方法,直到有一個(gè)返回false。
true:表示繼續(xù)流程(如調(diào)用下一個(gè)攔截器或處理器)
返回false后:表示流程中斷(如登錄檢查失敗),不會(huì)繼續(xù)調(diào)用其他的攔截器或處理器,
調(diào)用triggerAfterCompletion方法,此時(shí)this.interceptorIndex指向上一個(gè)返回true的interceptor的位置,
所以它會(huì)按逆序執(zhí)行所有返回true的interceptor的afterCompletion方法。
*/
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
/**
按照逆序執(zhí)行所有interceptor的postHandle方法
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
/**
從最后一次preHandle成功的interceptor處逆序執(zhí)行afterCompletion方法。
*/
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);
}
}
}
}
}