錯誤場景
驗證請求的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 請求,日志輸出如下:
回應體:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/336233.html
標籤:java
上一篇:Java的第一遍學習筆記 IO流
下一篇:充滿爭議的 Lombok
