Spring MVC的執行流程圖And源碼淺析(挺重要的呀)

先上圖:

  1. 百度裏的:
    在這裏插入圖片描述
  2. 自己仿着畫的
    在這裏插入圖片描述
  3. BigDevil_ 畫的
    在這裏插入圖片描述

再上文字描述:

轉載自:一頁知秋否

SpringMVC的具體工作原理

1、客戶端用戶發送請求至前端控制器DispatcherServlet。

2、 DispatcherServlet收到請求調用HandlerMapping處理器映射器。

3、 HandlerMapping處理器映射器找到具體的處理器(可以根據xml配置、註解進行查找),生成處理器對象及處理器攔截器(如果有則生成)一併返回給DispatcherServlet。

4、DispatcherServlet調用HandlerAdapter處理器適配器,HandlerAdapter經過適配調用具體的處理器(Controller,也叫後端控制器)。

5、Controller控制器執行完成返回ModelAndView,HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet。

6、 DispatcherServlet前端控制器將ModelAndView傳給ViewReslover視圖解析器。

7、 ViewReslover解析後返回具體View。

8、DispatcherServlet根據View進行渲染視圖(即將模型數據填充至視圖中),並返回給客戶端用戶。


最後上源碼:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	boolean multipartRequestParsed = false;

	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

	try {
		ModelAndView mv = null;
		Exception dispatchException = null;

		try {
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);
               

// -------------- 這是 前端控制器 請求查詢 處理器 的過程 start ----------------
			// Determine handler for the current request.
            // 1、請求HandlerMapping處理器映射器查詢Handler處理器
            // 返回HandlerExecutionChain處理執行鏈:1~n個攔截器和處理器handler
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}
// -------------- 這是 前端控制器 請求查詢 處理器 的過程 end ----------------
      
      
               
// -------------- 這是 前端控制器 請求執行 處理器 的過程 start ----------------
			// Determine handler adapter for the current request.
            // 2、根據處理器執行鏈的處理器對象獲取處理器適配器
            // 先從處理器執行鏈HandlerExecutionChain中獲取處理器對象Handler
            // 再從處理器Handler對象獲取處理器適配器HandlerAdapter
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				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;
				}
			}
			
            //--------調用preHandle-----------
            // 3、正序遍歷HandlerExecutionChain的攔截器數組
            // 依次執行攔截器的preHandle方法
            // 提示:下面的mappedHandler即爲HandlerExecutionChain對象
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			// Actually invoke the handler.
            // --------調用 目標方法------
         	// 4、HandlerAdapter處理器適配器調用handle方法獲取ModelAndView對象
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}

			applyDefaultViewName(request, mv);
             // --------調用 postHandle------
             // 5、逆序遍歷HandlerExecutionChain的攔截器數組
             // 依次執行攔截器的postHandle方法
             // 提示:下面的mappedHandler即爲HandlerExecutionChain對象
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
// -------------- 這是 前端控制器 請求執行 處理器 的過程 end ----------------
           


// -------------- 這是 前端控制器 請求解析 視圖 的過程 start ----------------
        // (方法的詳細內容見下面的processDispatchResult方法)
        // 6、請求視圖解析器解析ModelAndView對象
        // 並調用View對象的render方法真正的實際渲染視圖
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
// -------------- 這是 前端控制器 請求解析 視圖 的過程 end ----------------
           
           
	}
	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) {
			 /**
			 * Apply afterConcurrentHandlerStarted callback on mapped AsyncHandlerInterceptors.
			 */
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
			}
		}
		else {
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}
}


// 接第6步:請求視圖解析器解析視圖(詳細見下面的processDispatchResult方法)
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

	boolean errorView = false;

	if (exception != null) {
		if (exception instanceof ModelAndViewDefiningException) {
			logger.debug("ModelAndViewDefiningException encountered", exception);
			mv = ((ModelAndViewDefiningException) exception).getModelAndView();
		}
		else {
			Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
			mv = processHandlerException(request, response, handler, exception);
			errorView = (mv != null);
		}
	}

	// Did the handler return a view to render?
	if (mv != null && !mv.wasCleared()) {
        // 6.1 前端控制器請求視圖解析器解析ModelAndView對象(render的詳細代碼見下面)
        // 渲染給定的ModelAndView,這是處理請求的最後一個階段。
        // 它可能涉及通過名稱解析視圖。
		render(mv, request, response);
		if (errorView) {
			WebUtils.clearErrorRequestAttributes(request);
		}
	}
	else {
		if (logger.isDebugEnabled()) {
			logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
					"': assuming HandlerAdapter completed request handling");
		}
	}

	if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
		// Concurrent handling started during a forward
		return;
	}

	if (mappedHandler != null) {
        // 6.2 逆序遍歷HandlerExecutionChain的攔截器數組
        // 依次執行攔截器的afterCompletion方法
        // 提示:下面的mappedHandler即爲HandlerExecutionChain對象
		mappedHandler.triggerAfterCompletion(request, response, null);
	}
}


// 接第6.1步:前端控制器請求視圖解析器解析ModelAndView對象(詳細代碼在下面)
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	// Determine locale for request and apply it to the response.
	Locale locale = this.localeResolver.resolveLocale(request);
	response.setLocale(locale);

	View view;
	if (mv.isReference()) {
		// We need to resolve the view name.
        // 6.1.1 通過名稱解析視圖
		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
		if (view == null) {
			throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
					"' in servlet with name '" + getServletName() + "'");
		}
	}
	else {
		// No need to lookup: the ModelAndView object contains the actual View object.
        // 6.1.2 獲取View對象
		view = mv.getView();
		if (view == null) {
			throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
					"View object in servlet with name '" + getServletName() + "'");
		}
	}

	// Delegate to the View object for rendering.
	if (logger.isDebugEnabled()) {
		logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
	}
	try {
        // 6.1.3 調用View對象的render來呈現視圖
        // 渲染指定模型的視圖。
        // 第一步是準備請求:在JSP的情況下,這意味着將模型對象設置爲請求屬性。
        // 第二步是視圖的實際渲染
		view.render(mv.getModelInternal(), request, response);
	}
	catch (Exception ex) {
		if (logger.isDebugEnabled()) {
			logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
					getServletName() + "'", ex);
		}
		throw ex;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章