详述SpringMVC请求处理过程

一、引入

接上篇 详述load-on-startup标签的作用,本片来介绍SpringMVC中DispatcherServlet对象处理请求的过程

二、SpringMVC请求处理过程

1.用户端向服务器发送请求。

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);//注意这里的service方法是父类的service方法
	}
}

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);//注意这里的doGet()方法
         } 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);//注意这里的doService方法
	 }
	 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,是抽象方法,DispatcherServlet类重写了该方法,代码如下:

@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<String, Object> attributesSnapshot = null;
	if (WebUtils.isIncludeRequest(request)) {
		attributesSnapshot = new HashMap<String, Object>();
		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);//注意这里的doDispatch()方法
	}
	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);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				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);
		}
		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);
			}
		}
	}
}

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方法
	}
}
发布了91 篇原创文章 · 获赞 10 · 访问量 8013

猜你喜欢

转载自blog.csdn.net/Liuxiaoyang1999/article/details/105123649
今日推荐