springmvc的DispatcherServlet源碼——doDispatch方法解析


DispatcherServlet的doDispatch方法主要用作職責調度工作,本身主要用於控制流程,主要職責如下:

 

1、文件上傳解析,如果請求類型是multipart將通過MultipartResolver進行文件上傳解析;

2、通過HandlerMapping,將請求映射到處理器(返回一個HandlerExecutionChain,它包括一個處理器、多個HandlerInterceptor攔截器);

3、通過HandlerAdapter支持多種類型的處理器(HandlerExecutionChain中的處理器);

4、調用HandlerExecutionChain的interceptor和handler

5、解析視圖、處理異常,渲染具體的視圖等;

 

    1. 1:doDispatch方法中:如下:

/**
     * Process the actual dispatching to the handler. //處理實際調度處理器
     * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.    //處理程序將通過按順序的servlet的處理器映射器獲得。
     * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters //處理器適配器將通過查詢servlet的安裝的處理器適配器來獲得
     * to find the first that supports the handler class.                       //找到支持處理程序類的第一個。
     * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers //所有HTTP方法都由此方法處理。 這取決於處理器適配器或處理程序
     * themselves to decide which methods are acceptable.                      //自己決定哪些方法是可以接受的。
     * @param request current HTTP request                //請求當前HTTP請求
     * @param response current HTTP response               //響應當前的HTTP響應
     * @throws Exception in case of any kind of processing failure  //任何類型的處理失敗的例外 */
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        
     HttpServletRequest processedRequest
= request;  //processedRequest是經過checkMultipart方法處理過的request請求 HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try {
          //1、文件上傳解析,如果請求類型是multipart將通過MultipartResolver進行文件上傳解析;   processedRequest
= checkMultipart(request); multipartRequestParsed = (processedRequest != request);
          //2.通過HandlerMapping,將請求映射到處理器(返回一個HandlerExecutionChain,它包括一個處理器、多個HandlerInterceptor攔截器);
// Determine handler for the current request.   確定當前請求的處理程序。 mappedHandler = getHandler(processedRequest);      //解析第一個方法 if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; }           //3、通過HandlerAdapter支持多種類型的處理器(HandlerExecutionChain中的處理器);   // Determine handler adapter for the current request.  確定當前請求的處理程序適配器。 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());    //解析第二個方法 // Process last-modified header, if supported by the handler.  如果處理程序支持,則處理最后修改的頭文件。 String method = request.getMethod();    //得到當前的http方法。   boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) {    //處理http的head方法。這種方法應該很少用   long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } }           //4.1調用HandlerExecutionChain的interceptor   if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }           //4.2執行解析handler中的args,調用(invoke) controller的方法。得到視圖   // Actually invoke the handler.  實際上調用處理程序。 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());    //解析第三個方法 if (asyncManager.isConcurrentHandlingStarted()) { return; }           //4.3調用HandlerExecutionChain的interceptor   applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; }
        //5.解析視圖、處理異常   processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }
catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion  而不是后處理和完成后 if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request.  清理多部分請求使用的資源。 if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }

    1.2: DispatcherServlet類中 找到 getHandler

/**
     * Return the HandlerExecutionChain for this request.  //返回該請求的處理程序執行鏈
     * <p>Tries all handler mappings in order.        //嘗試按順序處理所有的處理程序映射。
     * @param request current HTTP request          //請求當前HTTP請求
     * @return the HandlerExecutionChain, or {@code null} if no handler could be found  //處理程序執行鏈或代碼返回null,如果沒有找到處理程序 */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
          //只會調用一個handler進行處理  
return handler; } } return null; }

    1.3:我們轉而去找HandlerMapping的getHander()發現HandlerMapping是一個接口,找到了實現類

/**
     * Look up a handler for the given request, falling back to the default  //查找給定請求的處理程序,回到默認值
     * handler if no specific one is found.                     //處理程序,如果沒有找到特定的。
     * @param request current HTTP request                    //請求當前HTTP請求
     * @return the corresponding handler instance, or the default handler //相應的處理程序實例或默認處理程序
     * @see #getHandlerInternal                          //得到內部處理程序 */
    @Override
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     //從實現類中獲得處理方法 Object handler
= getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler?    //Bean名稱或解決的處理程序? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); }      //獲得處理程序執行鏈 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }

     1.4:

/**
     * Build a {@link HandlerExecutionChain} for the given handler, including     //為給定的處理程序構建一個鏈接處理程序執行鏈,包括
     * applicable interceptors.                                 //適用攔截器。
     * <p>The default implementation builds a standard {@link HandlerExecutionChain} //默認實現構建一個標准的鏈接處理程序執行鏈
     * with the given handler, the handler mapping's common interceptors, and any  //與給定的處理程序,處理程序映射的常見攔截器和任何
     * {@link MappedInterceptor}s matching to the current request URL. Interceptors //映射映射攔截器與當前請求URL匹配。攔截器
     * are added in the order they were registered. Subclasses may override this   //按照注冊順序添加。 子類可以覆蓋此
     * in order to extend/rearrange the list of interceptors.               //以便擴展/重新排列攔截器列表。
     * <p><b>NOTE:</b> The passed-in handler object may be a raw handler or a     //注意:傳入處理程序對象可能是原始處理程序或
     * pre-built {@link HandlerExecutionChain}. This method should handle those    //預制鏈接處理程序執行鏈。 這種方法應該處理那些
     * two cases explicitly, either building a new {@link HandlerExecutionChain}   //建立一個新的鏈接處理程序執行鏈
     * or extending the existing chain.                            //或擴展現有的鏈。
     * <p>For simply adding an interceptor in a custom subclass, consider calling   //為了簡單地在自定義子類中添加攔截器,請考慮調用
     * {@code super.getHandlerExecutionChain(handler, request)} and invoking      //代碼:得到父類處理程序執行鏈(處理器,請求)}並調用
     * {@link HandlerExecutionChain#addInterceptor} on the returned chain object.   //{@鏈接處理程序執行鏈、添加攔截器}在返回的鏈對象上。
     * @param handler the resolved handler instance (never {@code null})        //處理程序解析的處理程序實例(代碼從不為空)
     * @param request current HTTP request                          //請求當前HTTP請求
     * @return the HandlerExecutionChain (never {@code null})              //處理程序執行鏈(代碼從不為空)
     * @see #getAdaptedInterceptors()                            //獲得適應的攔截器 */
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        //如果沒有獲得則創建一個
     HandlerExecutionChain chain
= (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));      //獲得IP地址及端口后的URL地址 String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
     //在HandlerExecutionChain中添加攔截器
     // 遍歷 SpringMVC 容器的所有攔截器

     for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
       // 判斷攔截器類型,屬於 MappedInterceptor,則先匹配路徑,否則直接添加
if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
          //根據lookupPath來獲取Interceptor
          if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; }

    結論:處理器執行鏈=1個hanlder+N個Interceptor

 

    2.1:HandlerAdaptor執行流程(進入方法在1.1)

/**
     * Return the HandlerAdapter for this handler object.      //返回:該處理程序對象的處理程序適配器。
     * @param handler the handler object to find an adapter for  //傳入的參數:處理處理程序對象以找到適配器
     * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.  
     */    //拋出的異常:如果找不到處理程序適配器,則Servlet異常。這是一個致命錯誤。
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
     //遍歷所有的handlerAdapters
for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace("Testing handler adapter [" + ha + "]"); }
       //調用相應實現的support方法,排在最前面的優先調用
if (ha.supports(handler)) { return ha; } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }

     3.1:在這里發現了一個接口,找到它 的實現(進入方法在1.1)

/**
     * Use the given handler to handle this request.    //使用給定的處理程序來處理此請求。
     * The workflow that is required may vary widely.    //所需的工作流程可能會有很大差異。
     * @param request current HTTP request           //請求當前HTTP請求
     * @param response current HTTP response          //響應當前的HTTP響應
     * @param handler handler to use. This object must have previously been passed  //處理程序處理程序使用 此對象必須先前已被傳遞
     * to the {@code supports} method of this interface, which must have        //到這個接口的{@code支持}方法,它必須具有
     * returned {@code true}.                                  //已返回{@code true}。
     * @throws Exception in case of errors                          //異常情況下出錯
     * @return ModelAndView object with the name of the view and the required     //ModelAndView對象具有視圖的名稱和必需
     * model data, or {@code null} if the request has been handled directly      //模型數據,或{@code null},如果請求已被直接處理 */
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

     3.2接口的各個實現

    3.3這里我們用的是SimpleControllerHandlerAdapter

public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
     //判斷是否是Controller類  
return (handler instanceof Controller); }    //執行Controller的handleRequest方法   @Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {       //本質是執行Controller的handleRequest方法   return ((Controller) handler).handleRequest(request, response); } @Override public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM