阿里四面之Spring Exception的原理解析
錯(cuò)誤場景

驗(yàn)證請求的Token合法性的Filter。Token校驗(yàn)失敗時(shí),直接拋?zhàn)远x異常,移交給Spring處理:

測試HTTP請求:

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

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

當(dāng)所有Filter被執(zhí)行完畢,Spring才會(huì)處理Servlet相關(guān),而DispatcherServlet才是整個(gè)Servlet處理核心,它是前端控制器設(shè)計(jì)模式,提供 Spring Web MVC 的集中訪問點(diǎn)并負(fù)責(zé)職責(zé)的分派。
在這,Spring處理了請求和處理器的對應(yīng)關(guān)系及統(tǒng)一異常處理。
Filter內(nèi)異常無法被統(tǒng)一處理,就是因?yàn)楫惓L幚戆l(fā)生在 DispatcherServlet#doDispatch()

但此時(shí),過濾器已全部執(zhí)行完。
Spring異常統(tǒng)一處理 ControllerAdvice如何被Spring加載并對外暴露? WebMvcConfigurationSupport#handlerExceptionResolver()
實(shí)例化并注冊一個(gè)ExceptionHandlerExceptionResolver 的實(shí)例

最終按下圖調(diào)用棧,Spring 實(shí)例化了ExceptionHandlerExceptionResolver類。

ExceptionHandlerExceptionResolver實(shí)現(xiàn)了InitializingBean
重寫 afterPropertiesSet()

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

所有被 @ControllerAdvice 注解的異常處理器,都會(huì)在 ExceptionHandlerExceptionResolver 實(shí)例化時(shí)自動(dòng)掃描并裝載在其exceptionHandlerAdviceCache。
initHandlerExceptionResolvers
當(dāng)?shù)谝淮握埱蟀l(fā)生時(shí),DispatcherServlet#initHandlerExceptionResolvers() 將獲取所有注冊到 Spring 的 HandlerExceptionResolver 實(shí)例(ExceptionHandlerExceptionResolver正是),存到handlerExceptionResolvers

ControllerAdvice如何被Spring消費(fèi)并處理異常? DispatcherServlet doDispatch()

執(zhí)行用戶請求時(shí),當(dāng)查找、執(zhí)行請求對應(yīng)的 handler 過程中異常時(shí):
會(huì)把異常值賦給 dispatchException再移交 processDispatchResult() processDispatchResult

當(dāng)Exception非空時(shí),繼續(xù)移交
processHandlerException

從 handlerExceptionResolvers 獲取有效的異常解析器以解析異常。
這里的 handlerExceptionResolvers 一定包含聲明的IllegalRequestExceptionHandler#IllegalRequestException 的異常處理器的 ExceptionHandlerExceptionResolver 包裝類。
修正
為利用到 Spring MVC 的異常處理機(jī)制,改造Filter:
手動(dòng)捕獲異常將異常通過 HandlerExceptionResolver 進(jìn)行解析處理
據(jù)此,修改 PermissionFilter,注入 HandlerExceptionResolver:

然后,在 doFilter 捕獲異常并移交 HandlerExceptionResolver:

現(xiàn)在再用錯(cuò)誤 Token 請求,日志輸出如下:

響應(yīng)體:

到此這篇關(guān)于阿里四面之Spring Exception的原理解析的文章就介紹到這了,更多相關(guān)Spring Exception原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot異常: nested exception is java.lang.NoClassDefFoundError: javax/servlet/ServletContext解決方案
- 解決SpringBoot ClassPathResource的大坑(FileNotFoundException)
- 關(guān)于springcloud報(bào)錯(cuò)報(bào)UnsatisfiedDependencyException的問題
- spring5 SAXParseException:cvc-elt.1: 找不到元素“beans 的聲明詳解
- 深入學(xué)習(xí)Spring Boot排查 @Transactional 引起的 NullPointerException問題
相關(guān)文章
spring boot+spring cache實(shí)現(xiàn)兩級緩存(redis+caffeine)
這篇文章主要介紹了spring boot+spring cache實(shí)現(xiàn)兩級緩存(redis+caffeine),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02
深入理解SpringBoot?最大連接數(shù)及最大并發(fā)數(shù)
SpringBoot能支持的最大并發(fā)量主要看其對Tomcat的設(shè)置,可以在配置文件中對其進(jìn)行更改,本文就來介紹一下SpringBoot?最大連接數(shù)及最大并發(fā)數(shù),感興趣的可以了解一下2023-08-08
Java?Stream?流中?Collectors.toMap?的用法詳解
這篇文章主要介紹了Stream?流中?Collectors.toMap?的用法,Collectors.toMap()方法是把List轉(zhuǎn)Map的操作,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01
Spring Security登錄添加驗(yàn)證碼的實(shí)現(xiàn)過程
這篇文章主要介紹了Spring Security登錄添加驗(yàn)證碼的實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11

