1. 程式人生 > >精盡Spring MVC原始碼分析 - HandlerMapping 元件(二)之 HandlerInterceptor 攔截器

精盡Spring MVC原始碼分析 - HandlerMapping 元件(二)之 HandlerInterceptor 攔截器

> 該系列文件是本人在學習 Spring MVC 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋 [Spring MVC 原始碼分析 GitHub 地址](https://github.com/liu844869663/spring-framework) 進行閱讀 > > Spring 版本:5.2.4.RELEASE > > 該系列其他文件請檢視:[**《精盡 Spring MVC 原始碼分析 - 文章導讀》**](https://www.cnblogs.com/lifullmoon/p/14123963.html) ## HandlerMapping 元件 HandlerMapping 元件,請求的**處理器匹配器**,負責為請求找到合適的 `HandlerExecutionChain` 處理器執行鏈,包含處理器(`handler`)和攔截器們(`interceptors`) - `handler` 處理器是 Object 型別,可以將其理解成 HandlerMethod 物件(例如我們使用最多的 `@RequestMapping` 註解所標註的方法會解析成該物件),包含了方法的所有資訊,通過該物件能夠執行該方法 - `HandlerInterceptor` 攔截器對處理請求進行**增強處理**,可用於在執行方法前、成功執行方法後、處理完成後進行一些邏輯處理 由於 HandlerMapping 元件涉及到的內容比較多,考慮到內容的排版,所以將這部分內容拆分成了四個模組,依次進行分析: - [**《HandlerMapping 元件(一)之 AbstractHandlerMapping》**](https://www.cnblogs.com/lifullmoon/p/14137308.html) - [**《HandlerMapping 元件(二)之 HandlerInterceptor 攔截器》**](https://www.cnblogs.com/lifullmoon/p/14137358.html) - **《HandlerMapping 元件(三)之 AbstractHandlerMethodMapping》** - **《HandlerMapping 元件(四)之 AbstractUrlHandlerMapping》** ## HandlerMapping 元件(二)之 HandlerInterceptor 攔截器 在上一篇[**《HandlerMapping 元件(一)之 AbstractHandlerMapping》**](https://www.cnblogs.com/lifullmoon/p/14137308.html)文件中分析了 HandlerMapping 元件的 AbstractHandlerMapping 抽象類,在獲取`HandlerExecutionChain` 處理器執行鏈時,會去尋找匹配的 HandlerInterceptor 攔截器們,並新增到其中。那麼本文將分享 Spring MVC 的攔截器相關內容 ### HandlerInterceptor `org.springframework.web.servlet.HandlerInterceptor`,處理器攔截器介面,程式碼如下: ```java public interface HandlerInterceptor { /** * 前置處理,在 {@link HandlerAdapter#handle(HttpServletRequest, HttpServletResponse, Object)} 執行之前 */ default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** * 後置處理,在 {@link HandlerAdapter#handle(HttpServletRequest, HttpServletResponse, Object)} 執行成功之後 */ default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } /** * 完成處理,在 {@link HandlerAdapter#handle(HttpServletRequest, HttpServletResponse, Object)} 執行之後(無論成功還是失敗) * 條件:執行 {@link #preHandle(HttpServletRequest, HttpServletResponse, Object)} 成功的攔截器才會執行該方法 */ default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } } ``` ### HandlerExecutionChain `org.springframework.web.servlet.HandlerExecutionChain`,處理器執行鏈,也就是通過 HandlerMapping 元件為請求找到的處理物件,包含處理器(`handler`)和攔截器們(`interceptors`) #### 構造方法 ```java public class HandlerExecutionChain { /** * 處理器 */ private final Object handler; /** * 攔截器陣列 */ @Nullable private HandlerInterceptor[] interceptors; /** * 攔截器陣列。 * * 在實際使用時,會呼叫 {@link #getInterceptors()} 方法,初始化到 {@link #interceptors} 中 */ @Nullable private List interceptorList; /** * 已成功執行 {@link HandlerInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object)} 的位置 * * 在 {@link #applyPostHandle} 和 {@link #triggerAfterCompletion} 方法中需要用到,用於倒序執行攔截器的方法 */ private int interceptorIndex = -1; public HandlerExecutionChain(Object handler) { this(handler, (HandlerInterceptor[]) null); } public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors) { if (handler instanceof HandlerExecutionChain) { HandlerExecutionChain originalChain = (HandlerExecutionChain) handler; this.handler = originalChain.getHandler(); this.interceptorList = new ArrayList<>(); // 將原始的 HandlerExecutionChain 的 interceptors 複製到 this.interceptorList 中 CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList); // 將入參的 interceptors 合併到 this.interceptorList 中 CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList); } else { this.handler = handler; this.interceptors = interceptors; } } } ``` - `handler`:請求對應的處理器物件,可以先理解為 `HandlerMethod` 物件(例如我們常用的 `@RequestMapping` 註解對應的方法會解析成該物件),也就是我們的某個 Method 的所有資訊,可以被執行 - `interceptors`:請求匹配的攔截器陣列 - `interceptorList`:請求匹配的攔截器集合,至於為什麼要該屬性,我還沒看明白