SpringMAC之初识——详述SpringMVC请求处理过程

1.点击“查看”链接,向Web服务器发送/userinfo/toView.do请求

2.执行DispatcherServletservice(HttpServletRequest request, HttpServletResponse response)方法,该方法源自于其父类FrameworkServlet,代码如下:

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

	HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
	if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
		processRequest(request, response);
	}
	else {
		super.service(request, response);
	}
}

3.执行HttpServletservice(HttpServletRequest req, HttpServletResponse resp)方法,代码如下:

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
{
String method = req.getMethod();
	
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
         if (lastModified == -1) {
             // servlet doesn't support if-modified-since, no reason
             // to go through further expensive logic
             doGet(req, resp);
         } else {
             long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
             if (ifModifiedSince < lastModified) {
                 // If the servlet mod time is later, call doGet()
                 // Round down to the nearest second for a proper compare
                 // A ifModifiedSince of -1 will always be less
                 maybeSetLastModified(resp, lastModified);
                 doGet(req, resp);
             } else {
                 resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
             }
         }
		
     } else if (method.equals(METHOD_HEAD)) {
         long lastModified = getLastModified(req);
         maybeSetLastModified(resp, lastModified);
         doHead(req, resp);
		
     } else if (method.equals(METHOD_POST)) {
         doPost(req, resp);
         
     } else if (method.equals(METHOD_PUT)) {
         doPut(req, resp);
         
     } else if (method.equals(METHOD_DELETE)) {
         doDelete(req, resp);
         
     } else if (method.equals(METHOD_OPTIONS)) {
         doOptions(req,resp);
         
     } else if (method.equals(METHOD_TRACE)) {
         doTrace(req,resp);
         
     } else {
         //
         // Note that this means NO servlet supports whatever
         // method was requested, anywhere on this server.
         //
		
         String errMsg = lStrings.getString("http.method_not_implemented");
         Object[] errArgs = new Object[1];
         errArgs[0] = method;
         errMsg = MessageFormat.format(errMsg, errArgs);
         
         resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
     }
}

4.执行DispatcherServletdoGet(HttpServletRequest request, HttpServletResponse response)方法,该方法源自于其父类FrameworkServlet,代码如下:

@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
	
	processRequest(request, response);
}

5.执行DispatcherServletprocessRequest(HttpServletRequest request, HttpServletResponse response)方法,该方法源自于其父类FrameworkServlet,代码如下:

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
      
	 long startTime = System.currentTimeMillis();
	 Throwable failureCause = null;
     
	 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
	 LocaleContext localeContext = buildLocaleContext(request);
      
	 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
	 ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
      
	 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
	 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
      
	 initContextHolders(request, localeContext, requestAttributes);
      
	 try {
		 doService(request, response);
	 }
	 catch (ServletException ex) {
		 failureCause = ex;
		 throw ex;
	 }
	 catch (IOException ex) {
		 failureCause = ex;
		 throw ex;
	 }
	 catch (Throwable ex) {
		 failureCause = ex;
		 throw new NestedServletException("Request processing failed", ex);
	 }
      
	 finally {
		 resetContextHolders(request, previousLocaleContext, previousAttributes);
		 if (requestAttributes != null) {
			 requestAttributes.requestCompleted();
		 }
          
		 if (logger.isDebugEnabled()) {
			 if (failureCause != null) {
				 this.logger.debug("Could not complete request", failureCause);
			 }
			 else {
				 if (asyncManager.isConcurrentHandlingStarted()) {
					 logger.debug("Leaving response open for concurrent processing");
				 }
				 else {
					 this.logger.debug("Successfully completed request");
				 }
			 }
		 }
           
		 publishRequestHandledEvent(request, response, startTime, failureCause);
	 }
}

6.执行DispatcherServletdoService(HttpServletRequest request, HttpServletResponse response)方法,该方法源自于其父类FrameworkServlet,代码如下:

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	if (logger.isDebugEnabled()) {
		String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
		logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
				" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
	}
       
	// Keep a snapshot of the request attributes in case of an include,
	// to be able to restore the original attributes after the include.
	Map attributesSnapshot = null;
	if (WebUtils.isIncludeRequest(request)) {
		attributesSnapshot = new HashMap();
		Enumeration attrNames = request.getAttributeNames();
		while (attrNames.hasMoreElements()) {
			String attrName = (String) attrNames.nextElement();
			if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
				attributesSnapshot.put(attrName, request.getAttribute(attrName));
			}
		}
	}
     
	// Make framework objects available to handlers and view objects.
	request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
	request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
	request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
	request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
     
     FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
	if (inputFlashMap != null) {
		request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
	}
	request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
	request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
     
	try {
		doDispatch(request, response);
	}
	finally {
		if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Restore the original attribute snapshot, in case of an include.
			if (attributesSnapshot != null) {
				restoreAttributesAfterInclude(request, attributesSnapshot);
			}
		}
	}
}

7.执行DispatcherServlet doDispatch(request, response)方法,代码如下:

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);
              
			// Determine handler for the current request.
			mappedHandler = getHandler(processedRequest);//11111111111
			if (mappedHandler == null || mappedHandler.getHandler() == null) {//2222222222
				noHandlerFound(processedRequest, response);
				return;
			}
              
		     // Determine handler adapter for the current request.
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//为当前请求确定Handler适配器,mappedHandler.getHandler()返回HandlerMethod对象
              
		     // 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;
				}
			}
              
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {//执行拦截器preHandle方法
				return;
			}
              
		     // Actually invoke the handler.
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//执行Handler方法,ha的值是RequestMappingHandlerAdapter类型的变量,执行其handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
              
		     if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}
              
			applyDefaultViewName(processedRequest, mv);
			mappedHandler.applyPostHandle(processedRequest, response, mv);//执行拦截器postHandle方法
		} catch (Exception ex) {
			dispatchException = ex;
		} catch (Throwable err) {
			// As of 4.3, we're processing Errors thrown from handler methods as well,
			// making them available for @ExceptionHandler methods and other scenarios.
			dispatchException = new NestedServletException("Handler dispatch failed", err);
		}
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//处理Handler返回结果
	}
 catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
 catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, 
			new NestedServletException("Handler processing failed", 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);
			}
		}
	}
}

标注一:

mappedHandler的类型为HandlerExecutionChain类型,该变量指向的对象通过HandlerMapping来获取,具体参见如下源码:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {//HandlerMapping接口,该接口的实现类对象实现了请求和Handler对象之间的映射

    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) {

             return handler;

         }

    }

    return null;

}

标注二: 如果Spring配置文件中没有配置,则发送一个没有Handler方法处理的请求时,mappedHandler 变量的值为null,否则为DefaultServletHttpRequestHandler类创建的对象。

8.执行DispatcherServlet processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception)方法,代码如下:

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()) {// mv不是空
		render(mv, request, response);// render [ˈrendər] 使成为 处理mv,渲染视图@@@@@@@@@@@@@@@
		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) {
		mappedHandler.triggerAfterCompletion(request, response, null); // 调用拦截器afterCompletion方法
	}
}

9.执行上步‘@@@@@@@@@@@’标注方法,该方法用于渲染视图,其代码如下:

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.
		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);// 视图解析器解析ViewName(视图名)得到View对象即将逻辑视图解析为物理视图,获取View对象
		if (view == null) {// 视图为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.
		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 {
		if (mv.getStatus() != null) {
			response.setStatus(mv.getStatus().value());
		}
		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;
	}
}

10.执行view.render(mv.getModelInternal(), request, response),该方法用于真正地渲染视图——>鼠标点击该行代码——>点击Ctrl+t,选择AbstractView——>进入AbstractView抽象类的render方法,代码如下:

@Override
public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
	if (logger.isTraceEnabled()) {
		logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
			" and static attributes " + this.staticAttributes);
	}
	
	Map mergedModel = createMergedOutputModel(model, request, response);
	prepareResponse(request, response);
	renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); //[mɜːdʒd]v.(使) 合并,结合
}

11.执行上步‘@@@@@@@@@@@’标注方法,该方法用于合并结果和模型——>鼠标点击该行代码——>点击Ctrl+t,选择InternalResourceView——>进入InternalResourceViewrenderMergedOutputModel方法,其代码如下:

@Override
protected void renderMergedOutputModel(
		Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
	
	// Expose the model object as request attributes.
	exposeModelAsRequestAttributes(model, request);
	
	// Expose helpers as request attributes, if any.
	exposeHelpers(request);
	
	// Determine the path for the request dispatcher.
	String dispatcherPath = prepareForRendering(request, response);
	
	// Obtain a RequestDispatcher for the target resource (typically a JSP).
	RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);//@@@@@@@@@@@@@@
	if (rd == null) {
		throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
				"]: Check that the corresponding file exists within your web application archive!");
	}
	
	// If already included or response already committed, perform include, else forward.
	if (useInclude(request, response)) {
		response.setContentType(getContentType());
		if (logger.isDebugEnabled()) {
			logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
		}
		rd.include(request, response);
	}
	
	else {
		// Note: The forwarded resource is supposed to determine the content type itself.
		if (logger.isDebugEnabled()) {
			logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
		}
		rd.forward(request, response); //请求转发@@@@@@@@@@@@@@
	}
}

结合上面两处‘@@@@@@@@@@@’标注代码可知该响应为request转发

你可能感兴趣的:(#SpringMAC,第三阶段)