成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

餓了么急招崗位:說說 Spring 攔截鏈的原理!

開發 前端
本文,我們深入探討了 Spring攔截鏈的實現原理和源碼分析,不僅可以幫助我們更好地使用 Spring提供的攔截器功能,還能讓我們在需要時自定義復雜的攔截邏輯,增強應用的靈活性和可維護性。?

這兩天,有小伙伴面了餓了么后端急招崗位,題目:說說 Spring攔截鏈的工作原理?結果他急眼了...

這篇文章,我們幫這個小伙伴扳回一局,從概念到原理,再到核心源碼,里里外外把 Spring攔截鏈的原理講個透,來,開干!

1. 什么是攔截鏈?

簡單來說,攔截鏈是一個處理請求的攔截器列表,按照一定的順序,一個一個地攔截并處理請求。每個攔截器都可以在請求處理前、處理后或完成后執行一些邏輯。

比如,我們可能需要在所有請求處理前進行權限驗證,在處理后記錄日志,或者在請求完成后釋放資源。這些操作可以通過定義不同的攔截器來實現,每個攔截器負責一個特定的任務。

2. Spring中的攔截鏈

在 Spring MVC中,攔截器鏈是通過HandlerInterceptor接口及其實現類來實現的。Spring的DispatcherServlet作為前端控制器(Front Controller),負責協調請求的各個階段,包括調用攔截器。

攔截器鏈的實現允許多個攔截器按照一定的順序對請求進行處理。每個攔截器都有機會在請求處理前后執行特定的邏輯,這為我們在請求處理流程中插入自定義邏輯提供了極大的靈活性。

3. 攔截鏈的核心組件

要理解攔截鏈的實現原理,首先需要了解 Spring MVC 中 4個核心組件的作用和互相之間的關系:

  • HandlerMapping:HandlerMapping負責將請求URL映射到具體的處理器(Handler)。處理器通常是一個控制器(Controller)的方法。Spring提供了多種HandlerMapping實現,如RequestMappingHandlerMapping,支持基于注解的映射。
  • HandlerAdapter:HandlerAdapter是負責執行具體處理器的組件。它知道如何調用特定類型的處理器,并返回一個ModelAndView對象,用于渲染視圖。
  • DispatcherServlet:DispatcherServlet是Spring MVC的核心組件,充當前端控制器。它接收所有的HTTP請求,協調HandlerMapping、HandlerAdapter和視圖解析等組件,最終將請求分發給合適的處理器進行處理。
  • HandlerInterceptor:HandlerInterceptor接口定義了攔截器的基本行為。通過實現該接口,可以在請求處理的不同階段插入自定義邏輯,如請求前、請求后或完成后的處理。

4. 攔截鏈的工作流程

了解了核心組件后,我們接下來分析攔截鏈是如何在這些組件之間協作,主要流程可以總結成下面 7個步驟:

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

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

5. 源碼分析

要深入理解攔截鏈的實現原理,我們需要查看Spring MVC的源碼。下面,我們將逐步分析DispatcherServlet、HandlerMapping、HandlerAdapter和HandlerInterceptor等組件的源碼,實現對攔截鏈的全面理解。

(1) DispatcherServlet的角色

DispatcherServlet是整個Spring MVC請求處理流程的中央樞紐。它承擔了接收請求、查找處理器、執行攔截器、調用處理器、渲染視圖等任務。

讓我們看看DispatcherServlet中與攔截鏈相關的關鍵源碼。

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. 應用攔截器的preHandle方法
            HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
            if (!applyPreHandle(processedRequest, response, mappedHandler, interceptors)) {
                return;
            }

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

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

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

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

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

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

(2) HandlerMapping的查找機制

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

來看一個簡單的getHandler方法的實現:

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

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

RequestMappingHandlerMapping的一個核心方法是getHandlerInternal:

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

(3) HandlerAdapter的適配邏輯

HandlerAdapter負責調用具體的處理器。Spring MVC提供了多種HandlerAdapter實現,如RequestMappingHandlerAdapter。

看看getHandlerAdapter和handle方法:

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

handlerAdapter是一個HandlerAdapter接口的實現,通過supports方法確定是否適配,然后調用handle方法執行處理器。

RequestMappingHandlerAdapter的handle方法示例:

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

(4) HandlerInterceptor的執行流程

在DispatcherServlet的doDispatch方法中,我們看到了攔截器的調用流程。下面深入看看這些攔截器是如何執行的。

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

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

在applyPreHandle方法中,DispatcherServlet會按照順序調用每個攔截器的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;
}

類似地,在applyPostHandle和triggerAfterCompletion方法中,攔截器的postHandle和afterCompletion方法依次被調用,且順序與preHandle相反。

6. 自定義攔截器的實現

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

public class MyInterceptor implements HandlerInterceptor {

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

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

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

注冊這個攔截器可以通過Java配置或XML配置。在Spring Boot中,可以通過實現WebMvcConfigurer接口來進行配置:

@Configuration
public class WebConfig implements WebMvcConfigurer {

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

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

(1) 攔截器的執行順序

如果定義了多個攔截器,Spring會按照注冊的順序執行preHandle方法,而執行postHandle和afterCompletion則是逆序的。例如:

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

執行順序:

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

這種設計允許后注冊的攔截器優先執行后置邏輯和完成邏輯。

7. 總結

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

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

責任編輯:趙寧寧 來源: 猿java
相關推薦

2025-03-18 08:30:00

Spring開發java

2015-03-31 18:19:37

餓了么動畫效果

2017-12-05 15:03:45

人工智能餓了么大數據

2017-07-21 14:48:47

AI物流O2O

2018-01-03 09:57:19

異地雙活數據庫

2017-10-27 15:44:24

餓了么張龍前端基礎設施

2020-07-06 08:40:36

阿里餓了么思考

2017-06-12 09:13:02

餓了么技術運營運維

2018-08-17 09:14:43

餓了么容器演進

2018-11-29 09:36:56

大數據調度系統

2018-02-28 10:45:10

技術變革混合云架構

2016-04-01 18:25:21

中國科技網

2016-08-26 22:36:18

大數據

2019-01-04 16:11:50

2011-08-30 10:22:14

MongoDB

2009-01-07 09:23:00

2024-03-28 10:37:44

IoC依賴注入依賴查找

2018-04-11 09:36:27

演進SLA實時計算

2015-08-06 17:49:18

容聯咻咻驗證碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品91久久| 精久久久| 亚洲成人一二区 | 日韩在线精品 | 久久午夜精品福利一区二区 | 成人免费视频在线观看 | 欧美精品一区久久 | 国产高清久久 | 精品福利一区二区三区 | 成年人在线视频 | 91婷婷韩国欧美一区二区 | 国产成人精品在线 | 91精品国产欧美一区二区成人 | 国产91亚洲精品一区二区三区 | 九九热在线视频免费观看 | 超碰地址 | 91久久| 久久99精品久久久久久国产越南 | 成人免费看片网 | 国内精品视频一区二区三区 | 超碰在线免费公开 | 亚洲情侣视频 | 国产一区二区在线播放视频 | 91传媒在线观看 | 国产成人精品久久 | 亚洲图片一区二区三区 | 日本二区在线观看 | 亚洲精品成人网 | 最新中文字幕在线 | 国产精品久久久久久久久污网站 | 四虎在线观看 | 神马久久久久久久久久 | 久久久久久久一区二区三区 | 激情综合五月天 | 久久免费视频1 | 人人九九精 | 精品一区二区三区四区视频 | 国产视频黄色 | 久久里面有精品 | 欧美日韩精品国产 | 国产高清免费视频 |