最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot全局異常處理機(jī)制中DispatcherServlet的處理流程和作用

 更新時間:2026年01月31日 09:15:27   作者:Qiuner  
本文深入解析Spring Boot全局異常處理機(jī)制,重點剖析DispatcherServlet的核心作用及其異常處理流程,詳細(xì)介紹了HandlerExceptionResolver接口及其三個默認(rèn)實現(xiàn)類的執(zhí)行順序和工作原理,通過源碼分析,展示了Spring MVC如何將異常轉(zhuǎn)換為響應(yīng)

1. 為什么一定要從 DispatcherServlet 講起

異常不是在 Controller 里被“解決”的,而是在框架層被“接管”的。

在 Spring MVC 中,這個“接管者”只有一個入口:

DispatcherServlet

無論你使用的是:

  • @ExceptionHandler
  • @ControllerAdvice
  • @ResponseStatus
  • Spring Boot 默認(rèn)的 /error

它們最終都必須經(jīng)過 DispatcherServlet 的調(diào)度與分發(fā)。

2. DispatcherServlet 在請求中的角色定位

在一次完整的請求處理中,DispatcherServlet 的職責(zé)可以概括為四步:

  1. 查找 Handler
  2. 執(zhí)行 Handler
  3. 處理返回值
  4. 處理異常

異常并不是一個“補(bǔ)丁邏輯”,而是 DispatcherServlet 的標(biāo)準(zhǔn)流程之一。

3. doDispatch:異常真正被捕獲的地方

DispatcherServlet 的核心方法是 doDispatch,異常處理的關(guān)鍵邏輯就在這里。

3.1 doDispatch 的整體結(jié)構(gòu)(簡化)

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
    try {
        // 1. 查找 Handler
        // 2. 執(zhí)行 Handler
    } catch (Exception ex) {
        dispatchException = ex;
    } catch (Throwable err) {
        dispatchException = new ServletException(err);
    }

    processDispatchResult(request, response, handler, dispatchException);
}

非常重要的一點:

DispatcherServlet 并不會在 catch 中直接處理異常,而是統(tǒng)一交給 processDispatchResult。

3.2 Throwable 為什么會被單獨捕獲?

catch (Throwable err) {
    dispatchException = new ServletException(err);
}

這里體現(xiàn)了一個非常關(guān)鍵的設(shè)計思想:

  • 框架不允許 Throwable 直接向外傳播
  • 所有異常最終都會被“標(biāo)準(zhǔn)化”為 Exception

這保證了后續(xù)異常解析鏈的統(tǒng)一性。

4. processDispatchResult:異常處理的真正入口

private void processDispatchResult(
        HttpServletRequest request,
        HttpServletResponse response,
        HandlerExecutionChain mappedHandler,
        Exception exception) {

    if (exception != null) {
        mv = processHandlerException(request, response, handler, exception);
    }
}

只要 exception != null,就會進(jìn)入異常處理流程。

5. processHandlerException:責(zé)任鏈的起點

protected ModelAndView processHandlerException(
        HttpServletRequest request,
        HttpServletResponse response,
        Object handler,
        Exception ex) {

    for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
        ModelAndView mv = resolver.resolveException(request, response, handler, ex);
        if (mv != null) {
            return mv;
        }
    }
    throw ex;
}

這一段代碼,是 Spring MVC 異常機(jī)制的靈魂。

從中可以明確看出三點:

  1. 異常處理是一個 Resolver 鏈
  2. 按順序逐個嘗試解析
  3. 誰先返回非 null,誰就“吃掉”異常

6. HandlerExceptionResolver 責(zé)任鏈模型

6.1 接口定義

public interface HandlerExceptionResolver {
    ModelAndView resolveException(
        HttpServletRequest request,
        HttpServletResponse response,
        Object handler,
        Exception ex);
}

設(shè)計目的非常明確:

給異常一個“翻譯成響應(yīng)”的機(jī)會

6.2 默認(rèn)的三個異常解析器

Spring MVC 默認(rèn)注冊了三個 Resolver:

Resolver作用
ExceptionHandlerExceptionResolver處理 @ExceptionHandler
ResponseStatusExceptionResolver處理 @ResponseStatus
DefaultHandlerExceptionResolver處理 Spring 內(nèi)置異常

它們構(gòu)成了一條有順序、有分工、有兜底的異常責(zé)任鏈。

7. Resolver 鏈的執(zhí)行順序是如何確定的

Resolver 并不是寫死的,而是通過初始化流程注入:

this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);

最終順序為:

  1. ExceptionHandlerExceptionResolver
  2. ResponseStatusExceptionResolver
  3. DefaultHandlerExceptionResolver

順序的設(shè)計邏輯是:

  • 用戶自定義優(yōu)先
  • 注解語義其次
  • 框架兜底最后

8. 異常是如何被“吃掉”的?

當(dāng)某個 Resolver 返回了非 null 的 ModelAndView:

if (mv != null) {
    return mv;
}

意味著:

  • 異常被成功解析
  • 后續(xù) Resolver 不再執(zhí)行
  • DispatcherServlet 不會再拋出異常

這也是為什么:

一個異常只會被一個 Resolver 處理

9. 如果所有 Resolver 都不處理會怎樣?

throw ex;

結(jié)果是:

  • 異常繼續(xù)向上拋
  • 對 Servlet 容器來說,這是一個未處理異常
  • 在 Spring Boot 中,通常會被 /error 接管(后續(xù)篇章重點)

10. 異常責(zé)任鏈流程圖

圖1 Spring MVC 異常解析責(zé)任鏈流程圖

11. 為什么說這是一個“非常優(yōu)雅的設(shè)計”

從源碼可以清楚看到:

  • 沒有 if-else 地獄
  • 沒有硬編碼異常類型
  • 完全遵循 開閉原則

你可以:

  • 插入自定義 Resolver
  • 調(diào)整順序
  • 替換默認(rèn)行為

而 DispatcherServlet 不需要修改一行代碼。

12. 本篇關(guān)鍵結(jié)論

到這一篇為止,我們已經(jīng)明確:

  1. DispatcherServlet 是異常處理的唯一入口
  2. 異常處理不是一個方法,而是一條責(zé)任鏈
  3. @ExceptionHandler 只是其中一個 Resolver
  4. Spring MVC 把“異常 → 響應(yīng)”的邏輯徹底解耦

但還有幾個繞不開的問題

  • @ExceptionHandler 是如何被掃描并匹配異常的?
  • @ControllerAdvice 為什么能全局生效?
  • ResponseBody 是如何寫入響應(yīng)的?
  • Spring Boot 為什么要額外引入 /error?

?? 這些問題,必須進(jìn)入 Resolver 內(nèi)部才能解釋清楚。

到此這篇關(guān)于Spring Boot全局異常處理機(jī)制中DispatcherServlet的處理流程和作用的文章就介紹到這了,更多相關(guān)Spring Boot異常處理機(jī)制DispatcherServlet內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

參考資料

  • Spring Framework Reference – Exception Handling
    https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-exceptionhandler.html
  • DispatcherServlet 源碼
    https://github.com/spring-projects/spring-framework

相關(guān)文章

  • mybatis-plus多表聯(lián)查join的實現(xiàn)

    mybatis-plus多表聯(lián)查join的實現(xiàn)

    本文主要介紹了mybatis-plus多表聯(lián)查join的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Apache?Maven3.6.0的下載安裝和環(huán)境配置(圖文教程)

    Apache?Maven3.6.0的下載安裝和環(huán)境配置(圖文教程)

    本文主要介紹了Apache?Maven3.6.0的下載安裝和環(huán)境配置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java的常見批量操作方法及注意事項

    Java的常見批量操作方法及注意事項

    Java作為一種強(qiáng)大的編程語言,提供了多種方法來有效地進(jìn)行批量數(shù)據(jù)處理,這篇文章主要介紹了Java的常見批量操作方法及注意事項的相關(guān)資料,需要的朋友可以參考下
    2025-06-06
  • 詳解SpringBoot通用配置文件(不定時更新)

    詳解SpringBoot通用配置文件(不定時更新)

    這篇文章主要介紹了SpringBoot通用配置文件詳解(不定時更新),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Java設(shè)計模式七大原則之合成復(fù)用原則詳解

    Java設(shè)計模式七大原則之合成復(fù)用原則詳解

    合成復(fù)用原則(Composite Reuse Principle),即盡量使用組合/聚合的方式,而不是使用繼承。本文將為大家具體介紹一下Java設(shè)計模式七大原則之一的合成復(fù)用原則,需要的可以參考一下
    2022-02-02
  • java對象拷貝常見面試題及應(yīng)答匯總

    java對象拷貝常見面試題及應(yīng)答匯總

    在本篇文章里小編給大家整理的是關(guān)于java對象拷貝常見面試題的相關(guān)內(nèi)容,需要的朋友們可以學(xué)習(xí)下。
    2020-02-02
  • Java自定義注解的詳解

    Java自定義注解的詳解

    這篇文章主要介紹了Java自定義注解的詳解的相關(guān)資料,Java注解提供了關(guān)于代碼的一些信息,但并不直接作用于它所注解的代碼內(nèi)容,需要的朋友可以參考下
    2017-08-08
  • SpringMVC中Json數(shù)據(jù)交互處理示例詳解

    SpringMVC中Json數(shù)據(jù)交互處理示例詳解

    這篇文章主要介紹了SpringMVC中Json數(shù)據(jù)交互處理的相關(guān)資料,分別講解了JSON的基本概念、構(gòu)成要素、數(shù)據(jù)類型、對象和數(shù)組的表示方法、字符串的轉(zhuǎn)義規(guī)則以及JSON與JavaScript的關(guān)系,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • 最新評論

    玉门市| 马公市| 太康县| 和平县| 宜君县| 宜君县| 肥西县| 治多县| 鱼台县| 明水县| 讷河市| 岳阳市| 宜兰市| 密山市| 临海市| 开鲁县| 乌拉特前旗| 濮阳市| 定日县| 英德市| 金门县| 烟台市| 双鸭山市| 黄浦区| 娱乐| 呈贡县| 镇远县| 海门市| 扎赉特旗| 阳泉市| 封开县| 曲松县| 宁海县| 定西市| 平阳县| 澄城县| 临武县| 无极县| 开化县| 古丈县| 桂东县|