1. 程式人生 > >springMvc請求到返回的流程request-->response

springMvc請求到返回的流程request-->response

springMvc核心類 : org.springframework.web.servlet.DispatcherServlet

核心方法:org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)

	/**
	 * Process the actual dispatching to the handler.
	 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
	 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
	 * 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
	 * themselves to decide which methods are acceptable.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @throws Exception in case of any kind of processing failure
	 */
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		int interceptorIndex = -1;

		try {
			ModelAndView mv;
			boolean errorView = false;

			try {
				//將請求轉換為多部分請求,並使多部分解析器可用
				processedRequest = checkMultipart(request);


				//將請求的requestUri 和容器所有的mapping比較是否存在
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					//"No mapping found for HTTP request with URI [" + requestUri +"] in DispatcherServlet with name '" + getServletName() + "'"
					//返回找不到對應requestUri
					return;
				}


				// Determine handler adapter for the current request.
				//返回傳入控制器的代理
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());


                // Process last-modified header, if supported by the handler.
				/**在http協議中,瀏覽器對訪問過的頁面快取後,它將會在以後訪問該頁面時,
					將會根據LastModified頭欄位指定的時間值生成If-Modified-Since頭欄位,
					作為快取頁面的最新更新時間。如果網頁的最後修改時間比If-Modified-Since頭欄位指定的時間早的話,
					web伺服器就會請求的頁面,如果自If-modified-Since指定的時間以來,網頁內容沒有被修改的話,
					伺服器就會返回一個304響應頭,一次告訴瀏覽器繼續使用已快取的頁面。*/
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}


				// Apply preHandle methods of registered interceptors.
				//應用已註冊的攔截器的預處理方法。
				/**攔截處理程式的執行。在HandlerMapping後決定,適當的處理程式物件,但在HandlerAdapter呼叫處理程式之前。
				 < p > DispatcherServlet處理執行鏈中的處理程式,包括任意數量的攔截器,最後是處理程式本身。
					使用此方法,每個攔截器可以決定中止執行鏈*/
				HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
				if (interceptors != null) {
					for (int i = 0; i < interceptors.length; i++) {
						HandlerInterceptor interceptor = interceptors[i];
						if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
							triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
							return;
						}
						interceptorIndex = i;
					}
				}

				// Actually invoke the handler.
				//實際呼叫處理程式
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				// Do we need view name translation?
				if (mv != null && !mv.hasView()) {
					mv.setViewName(getDefaultViewName(request));
				}

				// Apply postHandle methods of registered interceptors.
				//對已註冊的攔截器的方法進行應用。
				if (interceptors != null) {
					for (int i = interceptors.length - 1; i >= 0; i--) {
						HandlerInterceptor interceptor = interceptors[i];
						interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
					}
				}
			}
			catch (ModelAndViewDefiningException ex) {
				logger.debug("ModelAndViewDefiningException encountered", ex);
				mv = ex.getModelAndView();
			}
			catch (Exception ex) {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(processedRequest, response, handler, ex);
				errorView = (mv != null);
			}
			//使用了@ResponseBody註解,該註解直接將控制器中的返回值繫結到web響應體裡,如果返回的是字串,那麼該字串就顯示在瀏覽器上
			// Did the handler return a view to render?  是否返回檢視
			if (mv != null && !mv.wasCleared()) {
				render(mv, processedRequest, 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");
				}
			}

			// Trigger after-completion for successful outcome.
			//成功的結果觸發後續工作 interceptorComplete
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
		}

		catch (Exception ex) {
			// Trigger after-completion for thrown exception.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
			throw ex;
		}
		catch (Error err) {
			ServletException ex = new NestedServletException("Handler processing failed", err);
			// Trigger after-completion for thrown exception.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
			throw ex;
		}

		finally {
			// Clean up any resources used by a multipart request.
			if (processedRequest != request) {
				cleanupMultipart(processedRequest);
			}
		}
	}