阿裡四面之Spring Exception的原理解析

錯誤場景

驗證請求的Token合法性的Filter。Token校驗失敗時,直接拋自定義異常,移交給Spring處理:

測試HTTP請求:

日志輸出如下:說明IllegalRequestExceptionHandler未生效。

why?這就需要精通Spring異常處理流程瞭。

解析

當所有Filter被執行完畢,Spring才會處理Servlet相關,而DispatcherServlet才是整個Servlet處理核心,它是前端控制器設計模式,提供 Spring Web MVC 的集中訪問點並負責職責的分派。

在這,Spring處理瞭請求和處理器的對應關系及統一異常處理

Filter內異常無法被統一處理,就是因為異常處理發生在 DispatcherServlet#doDispatch()

但此時,過濾器已全部執行完

Spring異常統一處理 ControllerAdvice如何被Spring加載並對外暴露? WebMvcConfigurationSupport#handlerExceptionResolver()

實例化並註冊一個ExceptionHandlerExceptionResolver 的實例

最終按下圖調用棧,Spring 實例化瞭ExceptionHandlerExceptionResolver類。

ExceptionHandlerExceptionResolver實現瞭InitializingBean

 

重寫 afterPropertiesSet()

initExceptionHandlerAdviceCache

完成所有 ControllerAdvice 中的ExceptionHandler 初始化:查找所有 @ControllerAdvice 註解的 Bean,把它們放入exceptionHandlerAdviceCache。這裡即指自定義的IllegalRequestExceptionHandler

所有被 @ControllerAdvice 註解的異常處理器,都會在 ExceptionHandlerExceptionResolver 實例化時自動掃描並裝載在其exceptionHandlerAdviceCache。

initHandlerExceptionResolvers

當第一次請求發生時,DispatcherServlet#initHandlerExceptionResolvers() 將獲取所有註冊到 Spring 的 HandlerExceptionResolver 實例(ExceptionHandlerExceptionResolver正是),存到handlerExceptionResolvers

ControllerAdvice如何被Spring消費並處理異常? DispatcherServlet doDispatch()

執行用戶請求時,當查找、執行請求對應的 handler 過程中異常時:

會把異常值賦給 dispatchException再移交 processDispatchResult() processDispatchResult

當Exception非空時,繼續移交

processHandlerException

從 handlerExceptionResolvers 獲取有效的異常解析器以解析異常。

這裡的 handlerExceptionResolvers 一定包含聲明的IllegalRequestExceptionHandler#IllegalRequestException 的異常處理器的 ExceptionHandlerExceptionResolver 包裝類。

修正

為利用到 Spring MVC 的異常處理機制,改造Filter:

手動捕獲異常將異常通過 HandlerExceptionResolver 進行解析處理

據此,修改 PermissionFilter,註入 HandlerExceptionResolver:

然後,在 doFilter 捕獲異常並移交 HandlerExceptionResolver:

現在再用錯誤 Token 請求,日志輸出如下:

響應體:

到此這篇關於阿裡四面之Spring Exception的原理解析的文章就介紹到這瞭,更多相關Spring Exception原理內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: