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

一文詳解Spring攔截鏈的實(shí)現(xiàn)原理

 更新時(shí)間:2025年01月10日 08:17:44   作者:猿java  
在?Web應(yīng)用開發(fā)中,攔截器(Interceptor)是一種非常重要的機(jī)制,能夠在請求處理的各個(gè)階段進(jìn)行前置和后置處理,本文主要來探討一下?Spring?攔截鏈的實(shí)現(xiàn)原理,需要的可以了解下

在 Web應(yīng)用開發(fā)中,攔截器(Interceptor)是一種非常重要的機(jī)制,能夠在請求處理的各個(gè)階段進(jìn)行前置和后置處理。Spring框架提供了強(qiáng)大且靈活的攔截器機(jī)制,使開發(fā)者能夠輕松地在請求處理流程中插入自定義邏輯。

理解Spring攔截鏈的實(shí)現(xiàn)原理,不僅有助于我們更好地使用Spring提供的功能,還能讓我們在需要時(shí)自定義復(fù)雜的請求處理邏輯。

1. 什么是攔截鏈?

簡單來說,攔截鏈?zhǔn)且粋€(gè)處理請求的攔截器列表,按照一定的順序,一個(gè)一個(gè)地?cái)r截并處理請求。每個(gè)攔截器都可以在請求處理前、處理后或完成后執(zhí)行一些邏輯。

比如,我們可能需要在所有請求處理前進(jìn)行權(quán)限驗(yàn)證,在處理后記錄日志,或者在請求完成后釋放資源。這些操作可以通過定義不同的攔截器來實(shí)現(xiàn),每個(gè)攔截器負(fù)責(zé)一個(gè)特定的任務(wù)。

2. Spring中的攔截鏈

在Spring MVC中,攔截器鏈?zhǔn)峭ㄟ^HandlerInterceptor接口及其實(shí)現(xiàn)類來實(shí)現(xiàn)的。Spring的DispatcherServlet作為前端控制器(Front Controller),負(fù)責(zé)協(xié)調(diào)請求的各個(gè)階段,包括調(diào)用攔截器。

攔截器鏈的實(shí)現(xiàn)允許多個(gè)攔截器按照一定的順序?qū)φ埱筮M(jìn)行處理。每個(gè)攔截器都有機(jī)會(huì)在請求處理前后執(zhí)行特定的邏輯,這為我們在請求處理流程中插入自定義邏輯提供了極大的靈活性。

3. 攔截鏈的核心組件

要理解攔截鏈的實(shí)現(xiàn)原理,首先需要了解 Spring MVC中幾個(gè)核心組件的作用和互相之間的關(guān)系:

HandlerMappingHandlerMapping負(fù)責(zé)將請求URL映射到具體的處理器(Handler)。處理器通常是一個(gè)控制器(Controller)的方法。Spring提供了多種HandlerMapping實(shí)現(xiàn),如RequestMappingHandlerMapping,支持基于注解的映射。

HandlerAdapterHandlerAdapter是負(fù)責(zé)執(zhí)行具體處理器的組件。它知道如何調(diào)用特定類型的處理器,并返回一個(gè)ModelAndView對象,用于渲染視圖。

DispatcherServletDispatcherServlet是Spring MVC的核心組件,充當(dāng)前端控制器。它接收所有的HTTP請求,協(xié)調(diào)HandlerMapping、HandlerAdapter和視圖解析等組件,最終將請求分發(fā)給合適的處理器進(jìn)行處理。

HandlerInterceptorHandlerInterceptor接口定義了攔截器的基本行為。通過實(shí)現(xiàn)該接口,可以在請求處理的不同階段插入自定義邏輯,如請求前、請求后或完成后的處理。

4. 攔截鏈的工作流程

了解了核心組件后,我們來看攔截鏈?zhǔn)侨绾卧谶@些組件間協(xié)作的。

  • 請求到達(dá) DispatcherServlet:所有的HTTP請求首先由DispatcherServlet接收。
  • 查找 HandlerDispatcherServlet使用HandlerMapping查找與請求URL匹配的處理器(Handler)。
  • 應(yīng)用攔截器前置:在調(diào)用處理器之前,DispatcherServlet會(huì)調(diào)用已注冊的所有攔截器的preHandle方法。這些攔截器按照定義的順序依次執(zhí)行。如果任意一個(gè)攔截器的preHandle返回false,請求將被終止,后續(xù)的攔截器和處理器將不會(huì)執(zhí)行。
  • 調(diào)用 HandlerAdapter 執(zhí)行 Handler:所有前置攔截器的preHandle方法返回true后,DispatcherServlet會(huì)調(diào)用HandlerAdapter執(zhí)行具體的處理器方法(如Controller中的方法)。
  • 應(yīng)用攔截器后置:處理器執(zhí)行完成后,DispatcherServlet會(huì)調(diào)用攔截器的postHandle方法,這些攔截器按照定義的順序逆序執(zhí)行。
  • 渲染視圖DispatcherServlet使用視圖解析器(ViewResolver)渲染最終的視圖,如返回一個(gè)HTML頁面。
  • 完成攔截器:最后,DispatcherServlet調(diào)用攔截器的afterCompletion方法,通知攔截器請求已經(jīng)完成,同樣按逆序執(zhí)行。

這個(gè)流程確保了攔截器可以在請求處理的不同階段插入邏輯,例如驗(yàn)證、日志記錄、性能監(jiān)控等。

5. 源碼分析

要深入理解攔截鏈的實(shí)現(xiàn)原理,我們需要查看Spring MVC的源碼。下面,我們將逐步分析DispatcherServlet、HandlerMappingHandlerAdapterHandlerInterceptor等組件的源碼,實(shí)現(xiàn)對攔截鏈的全面理解。

5.1 DispatcherServlet的角色

DispatcherServlet是整個(gè)Spring MVC請求處理流程的中央樞紐。它承擔(dān)了接收請求、查找處理器、執(zhí)行攔截器、調(diào)用處理器、渲染視圖等任務(wù)。

讓我們看看DispatcherServlet中與攔截鏈相關(guān)的關(guān)鍵源碼。

public class DispatcherServlet extends FrameworkServlet {
    // ...其他代碼...

    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // ...初始化上下文...

        // 1. 查找處理器
        HandlerExecutionChain mappedHandler = getHandler(processedRequest);
        if (mappedHandler == null) {
            noHandlerFound(request, response);
            return;
        }

        HttpServletRequest webRequest = createWebRequest(request, response);
        try {
            // 2. 應(yīng)用攔截器的preHandle方法
            HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
            if (!applyPreHandle(processedRequest, response, mappedHandler, interceptors)) {
                return;
            }

            // 3. 調(diào)用處理器
            ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            // 4. 應(yīng)用攔截器的postHandle方法
            applyPostHandle(processedRequest, response, mappedHandler, mv, interceptors);

            // 5. 渲染視圖
            render(mv, request, response);

            // 6. 應(yīng)用攔截器的afterCompletion方法
            triggerAfterCompletion(processedRequest, response, mappedHandler, null, interceptors);
        } catch (Exception ex) {
            // 異常處理
            // ...
        }
    }

    // ...其他代碼...
}

從上面的代碼可以看出,DispatcherServlet在處理請求的過程中,依次執(zhí)行了查找處理器、應(yīng)用攔截器的preHandle、調(diào)用處理器、應(yīng)用攔截器的postHandle、渲染視圖以及應(yīng)用攔截器的afterCompletion方法的步驟。

5.2 HandlerMapping的查找機(jī)制

HandlerMapping用于將請求映射到具體的處理器。Spring MVC提供了多種HandlerMapping實(shí)現(xiàn),如基于注解的RequestMappingHandlerMapping。

來看一個(gè)簡單的getHandler方法的實(shí)現(xiàn):

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    return this.handlerMappings.getHandler(request);
}

這里,handlerMappings是一個(gè)List<HandlerMapping>,Spring會(huì)按照順序遍歷這些HandlerMapping,直到找到匹配的處理器。

RequestMappingHandlerMapping的一個(gè)核心方法是getHandlerInternal

@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    // 基于請求URL和HTTP方法,查找匹配的HandlerMethod
    // 返回一個(gè)HandlerMethod對象,包含控制器實(shí)例和方法信息
}

5.3 HandlerAdapter的適配邏輯

HandlerAdapter負(fù)責(zé)調(diào)用具體的處理器。Spring MVC提供了多種HandlerAdapter實(shí)現(xiàn),如RequestMappingHandlerAdapter。

看看getHandlerAdapterhandle方法:

protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    return handlerAdapter.handle(request, response, handler);
}

handlerAdapter是一個(gè)HandlerAdapter接口的實(shí)現(xiàn),通過supports方法確定是否適配,然后調(diào)用handle方法執(zhí)行處理器。

RequestMappingHandlerAdapterhandle方法示例:

@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 調(diào)用Controller方法,處理請求
    // 綁定請求參數(shù),執(zhí)行數(shù)據(jù)綁定和驗(yàn)證
    // 返回ModelAndView對象
}

5.4 HandlerInterceptor的執(zhí)行流程

DispatcherServletdoDispatch方法中,我們看到了攔截器的調(diào)用流程。下面深入看看這些攔截器是如何執(zhí)行的。

假設(shè)我們有一個(gè)HandlerExecutionChain對象,它包含了處理器和一組攔截器:

public class HandlerExecutionChain {
    private final Object handler;
    private final List<HandlerInterceptor> interceptors;
    
    // Getters and constructors
}

applyPreHandle方法中,DispatcherServlet會(huì)按照順序調(diào)用每個(gè)攔截器的preHandle方法:

protected boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler)
        throws Exception {

    HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
    if(!ObjectUtils.isEmpty(interceptors)) {
        for (HandlerInterceptor interceptor : interceptors) {
            if (!interceptor.preHandle(request, response, mappedHandler.getHandler())) {
                triggerAfterCompletion(request, response, mappedHandler, null, interceptors);
                return false;
            }
        }
    }
    return true;
}

類似地,在applyPostHandletriggerAfterCompletion方法中,攔截器的postHandleafterCompletion方法依次被調(diào)用,且順序與preHandle相反。

6. 自定義攔截器的實(shí)現(xiàn)

了解了攔截鏈的基礎(chǔ)后,我們來看看如何在Spring中自定義攔截器。下面是一個(gè)簡單的自定義攔截器示例:

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 請求處理前執(zhí)行
        System.out.println("Pre Handle method is Calling");
        return true; // 返回true繼續(xù)流程,返回false則中斷
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 請求處理后但視圖渲染前執(zhí)行
        System.out.println("Post Handle method is Calling");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // 視圖渲染后執(zhí)行
        System.out.println("Request and Response is completed");
    }
}

注冊這個(gè)攔截器可以通過Java配置或XML配置。在Spring Boot中,可以通過實(shí)現(xiàn)WebMvcConfigurer接口來進(jìn)行配置:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**") // 攔截所有請求
                .excludePathPatterns("/login"); // 排除特定路徑
    }
}

通過這樣的配置,MyInterceptor就會(huì)攔截所有請求,除了/login路徑。

6.1 攔截器的執(zhí)行順序

如果定義了多個(gè)攔截器,Spring會(huì)按照注冊的順序執(zhí)行preHandle方法,而執(zhí)行postHandleafterCompletion則是逆序的。例如:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new FirstInterceptor());
    registry.addInterceptor(new SecondInterceptor());
}

執(zhí)行順序:

  • FirstInterceptor.preHandle
  • SecondInterceptor.preHandle
  • SecondInterceptor.postHandle
  • FirstInterceptor.postHandle
  • SecondInterceptor.afterCompletion
  • FirstInterceptor.afterCompletion

這種設(shè)計(jì)允許后注冊的攔截器優(yōu)先執(zhí)行后置邏輯和完成邏輯。

7. 總結(jié)

本文,我們深入探討了 Spring攔截鏈的實(shí)現(xiàn)原理和源碼分析,從核心組件如DispatcherServlet、HandlerMapping、HandlerAdapterHandlerInterceptor的功能,到攔截鏈的工作流程,再到實(shí)際的源碼分析和自定義攔截器的實(shí)現(xiàn)。

理解這些原理,不僅可以幫助我們更好地使用 Spring提供的攔截器功能,還能讓我們在需要時(shí)自定義復(fù)雜的攔截邏輯,增強(qiáng)應(yīng)用的靈活性和可維護(hù)性。

到此這篇關(guān)于一文詳解Spring攔截鏈的實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)Spring攔截鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中版本兼容性處理的實(shí)現(xiàn)示例

    SpringBoot中版本兼容性處理的實(shí)現(xiàn)示例

    SpringBoot版本兼容性問題通常是由于依賴庫與SpringBoot版本不兼容引起的,本文主要介紹了SpringBoot中版本兼容性處理的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • mybatisPlus?FieldStrategy?策略作用小結(jié)

    mybatisPlus?FieldStrategy?策略作用小結(jié)

    MyBatis-Plus的FieldStrategy枚舉用于控制實(shí)體字段在插入、更新和查詢條件中的空值處理策略,下面就來詳細(xì)的介紹一下mybatisPlus?FieldStrategy?策略,感興趣的可以了解一下
    2025-12-12
  • 解決spring項(xiàng)目找不到Aspect依賴注解的問題

    解決spring項(xiàng)目找不到Aspect依賴注解的問題

    這篇文章主要介紹了解決spring項(xiàng)目找不到Aspect依賴注解的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • springboot如何配置上傳文件的maxRequestSize

    springboot如何配置上傳文件的maxRequestSize

    這篇文章主要介紹了springboot如何配置上傳文件的maxRequestSize,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java設(shè)計(jì)模式之java模板方法模式詳解

    Java設(shè)計(jì)模式之java模板方法模式詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式模板方法模式(Template)用法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-09-09
  • RepeatSubmit若依框架如何防止表單重復(fù)提交注解

    RepeatSubmit若依框架如何防止表單重復(fù)提交注解

    若依框架中的@RepeatSubmit注解用于防止表單重復(fù)提交,通過在控制器方法上添加該注解,并在前端頁面和JavaScript代碼中實(shí)現(xiàn)雙重校驗(yàn),可以確保同一用戶在短時(shí)間內(nèi)不會(huì)重復(fù)提交相同的表單
    2024-11-11
  • sqlmap 使用教程(從入門到進(jìn)階)

    sqlmap 使用教程(從入門到進(jìn)階)

    sqlmap是一款強(qiáng)大的開源 SQL 注入自動(dòng)化測試工具,支持識(shí)別并利用多種類型的 SQL 注入漏洞(Boolean-based、Time-based、Error-based、Stacked Queries 等),本文給大家介紹sqlmap使用教程,感興趣的朋友一起看看吧
    2016-11-11
  • springboot實(shí)現(xiàn)獲取當(dāng)前服務(wù)器IP及當(dāng)前項(xiàng)目使用的端口號(hào)Port

    springboot實(shí)現(xiàn)獲取當(dāng)前服務(wù)器IP及當(dāng)前項(xiàng)目使用的端口號(hào)Port

    這篇文章主要介紹了springboot實(shí)現(xiàn)獲取當(dāng)前服務(wù)器IP及當(dāng)前項(xiàng)目使用的端口號(hào)Port方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • java CompletableFuture實(shí)現(xiàn)異步編排詳解

    java CompletableFuture實(shí)現(xiàn)異步編排詳解

    這篇文章主要為大家介紹了java CompletableFuture實(shí)現(xiàn)異步編排詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • JAVA設(shè)計(jì)模式之訪問者模式詳解

    JAVA設(shè)計(jì)模式之訪問者模式詳解

    這篇文章主要介紹了JAVA設(shè)計(jì)模式之訪問者模式詳解,訪問者模式是對象的行為模式,訪問者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作,需要的朋友可以參考下
    2015-04-04

最新評(píng)論

班戈县| 漳平市| 太湖县| 奇台县| 礼泉县| 临泉县| 万宁市| 巴马| 郑州市| 聂荣县| 武定县| 福鼎市| 泸定县| 礼泉县| 安康市| 黄浦区| 五原县| 沽源县| 河西区| 大城县| 兰坪| 甘泉县| 平山县| 山阳县| 竹山县| 松溪县| 西城区| 仁寿县| 含山县| 左云县| 安西县| 贺兰县| 景宁| 镇巴县| 洪湖市| 丰原市| 青海省| 建德市| 墨竹工卡县| 建瓯市| 顺义区|