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

本文深入探讨了Spring MVC框架中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);
			}
		}
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值