Spring5 源码阅读笔记(5.2)DispatcherServlet 里的 doDispatch

本节内容

在写代码时都知道,在方法上添加 @RequestMapping 注解,可以让对应的 http 请求进来时,执行该方法,在源码中如何体现的呢?

小知识

入参前面加上 @PathVariable(“x”),能拿到 @RequestMapping("/{x}") 里的 x。

入参前面加上 @RequestParam(“x”),能拿到 URI 里 ?后面的 x 的值。
如果 @RequestParam 不加(),需要入参名和 URI 里的参数名一样。

doDispatch

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

			//这个方法很重要,重点看 见 5.2.2
			// Determine handler for the current request.
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			//获取跟HandlerMethod匹配的HandlerAdapter对象
			// 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();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}

			//请求所有拦截器里的preHandle方法,记录最后一个成功处理的索引interceptorIndex,
			//一旦有处理失败的,立即从interceptorIndex到0调用所有afterCompletion,返回false
			//一旦返回false,这里条件成立,直接返回,不会调用下面的postHandle
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			//调用到Controller具体方法,核心方法调用,重点看看 见5.2.3
			// Actually invoke the handler.
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

			applyDefaultViewName(processedRequest, mv);

			//从interceptorIndex开始到0请求拦截器数组里的所有postHandle方法
			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);
		}

		//视图渲染 见 5.2.4
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	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);
			}
		}
	}
}
发布了185 篇原创文章 · 获赞 271 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44367006/article/details/104933694