Spring-MVC-核心调用流程,MySQL万字精华总结

	long startTime = System.currentTimeMillis();
	Throwable failureCause = null;
	
	doService(request, response);

}

> 进入`doService`方法
> 
> 所在类:org.springframework.web.servlet.`DispatcherServlet`
```java
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logRequest(request);
		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);
				}
			}
		}
}

请求调用 核心入口

请求最终进入doDispatch方法

所在类:org.springframework.web.servlet.DispatcherServlet

	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 {
				// 文件上传解析,如果请求类型是multipart将通过
				// MultipartResolver进行文件上传解析
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);
				// 对当前请求匹配一个合适的 handler,重要方法
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// 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;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			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 {
				// 如果是multipart的请求,清空上传的multipart资源
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

::: warning 知识点
总结,getHandler方法的主要作用体现在以下几点:

  • 首先,从当前Request中拿到请求的URL
  • 然后,从映射关系中拿到HandlerMethod对象
  • 接着,把HandlerMethod对象封装到HandlerExecutionChain执行链中
  • 最后,在HandlerExecutionChain执行链的创建过程中会拿到整个容器中所有的拦截器(实现HandlerInterceptor接口的拦截器),和当前请求的URL进行匹配,如果匹配成功的话,就会把拦截器放到HandlerExecutionChain的数组中。
    :::

进入getHandler方法

所在类:org.springframework.web.servlet.DispatcherServlet

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// handlerMappering 实例容器不为空
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				// 获取 HandlerMethod 和过滤器链的包装类
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

进入getHandler方法

所在类:org.springframework.web.servlet.handler.AbstractHandlerMapping

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 根据请求的 URL 拿到对应的 HandlerMethod 对象
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}
		// 获取 HandlerMethod 和过滤器链的包装类
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		if (logger.isTraceEnabled()) {
			logger.trace("Mapped to " + handler);
		}
		else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
			logger.debug("Mapped to " + executionChain.getHandler());
		}
		// 是否是跨域请求,就是查看 request 请求头中是否有 Origin 属性
		if (CorsUtils.isCorsRequest(request)) {
			CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}

		return executionChain;
	}

进入getHandlerInternal方法

所在类:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		// 从request对象中获取 URL,/common/query2
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		this.mappingRegistry.acquireReadLock();
		try {
			// 根据 URL 从映射关系中找到对应的 HandlerMethod 对象
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			// 执行beanFactory.getBean的过程,获取Controller实例
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

::: warning 知识点
lookupHandlerMethod方法之所以可以从映射关系中拿到HandlerMethod对象,是因为AbstractHandlerMethodMapping类实现了InitializingBean接口,在afterPropertiesSet方法里建立好了映射关系。
:::

进入lookupHandlerMethod方法

所在类:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<>();
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
			// 匹配过程,是否符合 RequestMappingInfo 里的属性值
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// No choice but to go through all mappings...
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			matches.sort(comparator);
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				if (logger.isTraceEnabled()) {
					logger.trace(matches.size() + " matching mappings: " + matches);
				}
				if (CorsUtils.isPreFlightRequest(request)) {
					return PREFLIGHT_AMBIGUOUS_MATCH;
				}
				Match secondBestMatch = matches.get(1);
				// 如果两个 RequestMappinginfo 什么都相同,报错
				if (comparator.compare(bestMatch, secondBestMatch) == 0) {
					Method m1 = bestMatch.handlerMethod.getMethod();
					Method m2 = secondBestMatch.handlerMethod.getMethod();
					String uri = request.getRequestURI();
					throw new IllegalStateException(
							"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
				}
			}
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

::: warning 知识点
addMatchingMappings方法,主要一个匹配过程,匹配@RequestMapping注解中的属性值是否满足

 /*
  * consumes:指定处理请求的提交内容类型(Content-Type),
  * 	例如application/json, text/html;
  * produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
  * params: 指定request中必须包含某些参数值是,才让该方法处理。
  * headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
  * */
@RequestMapping(value = "/getUser",
    method = RequestMethod.GET,
    params = "username=jack",
    consumes = "application/json",
    produces = "application/json",
    headers = "Referer=http://www.xx.com/")

:::

返回getHandler,进入getHandlerExecutionChain方法

所在类:org.springframework.web.servlet.handler.AbstractHandlerMapping

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		// 如果没有获得则创建一个 HandlerExecutionChain
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
		// 获取当前的请求地址: /user/xxx
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		// 在 HandlerExecutionChain 中添加拦截器
		// 遍历 SpringMVC 容器的所有拦截器
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			// 判断拦截器类型,如果是 MappedInterceptor 类型
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				// 则先匹配路径后再添加到执行链
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				// 否则直接添加到执行链
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

::: warning 知识点
getHandlerExecutionChain中的HandlerInterceptor拦截器是Spring MVC中的,Spring AOP中的拦截器是MethodInterceptor
:::

拿到当前请求对应的handler后,

返回主流程,进入getHandlerAdapter方法

所在类:org.springframework.web.servlet.DispatcherServlet

/**
 * TODO : 根据 handlerMethod对象,找到合适的 HandlerAdapter对象,这里用到了策略模式
 */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					// 返回一个可以支持的HandlerAdapter 处理程序实例
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

::: warning 知识点

HandlerAdapter 是什么
HandlerAdapter是一个接口,充当自身与处理程序对象之间的桥梁,从而导致松散耦合设计。HandlerAdapter主要处理方法参数、相关注解、数据绑定、消息转换、返回值、调用视图解析器等。

  • RequestMappingHandlerMapping为当前的请求找到合适的处理程序方法。
  • RequestMappingHandlerAdapter执行这个处理程序方法,并为它提供反射调用所需要的参数。

HandlerAdapter UML 图

HandlerAdapter的4个实现类:

  1. SimpleServletHandlerAdapter: 适配实现 Servlet 接口的Handler, 默认调用其service方法
  1. SimpleControllerHandlerAdapter: 适配实现Controller 接口的Handler, 默认调用其 handleRequest 方法
  2. HttpRequestHandlerAdapter: 适配实现HttpRequestHandler 接口的 Handler, 默认调用其 handleRequest 方法
  3. RequestMappingHandlerAdapter: 适配被@RequestMapping注释的方式, 一般都是解析一个一个参数, 并且通过反射进行激活

HandlerAdapter 总结
HandlerAdapterSpring MVC中扩展机制的非常好的一个体现,,通过 HandlerAdapter这种设计模式,DispatcherServlet 就可以支持任何格式的Handler(这里的可以支持指在不改变 DispatcherServlet 的情况下),第二是HandlerAdapter 基于不同Handler实现不同实现类(策略模式),最后也是最重要的就是参数的解析与返回值的解析。

:::

::: danger 为什么要用HandlerAdapter适配器模式?
首先, Controller的定义有多种 ,一种是带@Controller注解的, 还可以写一个servlet 当做controller, 所以用适配器做适配,不同子类实现HandlerAdapter接口,定义自己的业务逻辑,每个子类都是适配某一种类型的控制器,有了HandlerAdapter,你只需要调用自己实现的handle方法,屏蔽了不一致的细节,对用户来说直接找到对应的处理方法,无须关系哪个实现方法,否则只能在DispatcherServlet里面通过ifelse来处理了。
:::

前置过滤器

返回主流程,进入applyPreHandle方法,前置过滤器

所在类:org.springframework.web.servlet.DispatcherServlet

/**
 * TODO : 调用所有的 HandlerInterceptor 拦截器并调用其 preHandler方法
 */
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 获取所有的拦截器
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				// 分别调用拦截器的 preHandle 方法
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				// 如果失败,记录最后一次拦截器的位置,倒序释放
				this.interceptorIndex = i;
			}
		}
		return true;
	}

返回主流程,进入handle方法,调用具体Controller的方法

最终会进入AbstractHandlerMethodAdapterhandle方法,

	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return handleInternal(request, response, (HandlerMethod) handler);
	}

进入handleInternal方法,

所在类:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				// 执行 HandlerMethod,返回 ModelAndView
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			// 执行 HandlerMethod,返回 ModelAndView
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}

进入invokeHandlerMethod方法,

所在类:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			// 获取数据绑定工厂  @InitBinder注解支持,
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			// Model工厂,收集了@ModelAttribute注解的方法
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
			//可调用的方法对象
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
				//设置参数解析器
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
				// 设置返回值解析器
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			// 设置参数绑定工厂
			invocableMethod.setDataBinderFactory(binderFactory);
			// 设置参数名称解析类
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			// 调用有 @ModelAttribute注解的方法。每次请求都会调用有 @ModelAttribute注解的方法
			//把 @ModelAttribute注解的方法的返回值存储到 ModelAndViewContainer对象的 map中了
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);
			// 异步处理
			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			asyncManager.setTaskExecutor(this.taskExecutor);
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			if (asyncManager.hasConcurrentResult()) {
				Object result = asyncManager.getConcurrentResult();
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				asyncManager.clearConcurrentResult();
				LogFormatUtils.traceDebug(logger, traceOn -> {
					String formatted = LogFormatUtils.formatValue(result, !traceOn);
					return "Resume with async result [" + formatted + "]";
				});
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}
			// Controller方法调用,重点看看
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

::: warning 知识点
invokeHandlerMethod方法主要进行了数据和参数的绑定、创建ModelAndViewContainer视图容器,以及相关初始化工作。
:::

进入invokeAndHandle方法

所在类:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		// 具体调用逻辑,重点看
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {


# 最后

每年转战互联网行业的人很多,说白了也是冲着高薪去的,不管你是即将步入这个行业还是想转行,学习是必不可少的。作为一个Java开发,学习成了日常生活的一部分,不学习你就会被这个行业淘汰,这也是这个行业残酷的现实。

如果你对Java感兴趣,想要转行改变自己,那就要趁着机遇行动起来。或许,这份**限量版的Java零基础宝典**能够对你有所帮助。

领取这份**Java零基础宝典****[只需要点击这里即可免费下载](https://gitee.com/vip204888/java-p7)**

![](https://img-blog.csdnimg.cn/img_convert/8aa110ff656e0797ad67bebdfab38a6a.png)

rRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {


# 最后

每年转战互联网行业的人很多,说白了也是冲着高薪去的,不管你是即将步入这个行业还是想转行,学习是必不可少的。作为一个Java开发,学习成了日常生活的一部分,不学习你就会被这个行业淘汰,这也是这个行业残酷的现实。

如果你对Java感兴趣,想要转行改变自己,那就要趁着机遇行动起来。或许,这份**限量版的Java零基础宝典**能够对你有所帮助。

领取这份**Java零基础宝典****[只需要点击这里即可免费下载](https://gitee.com/vip204888/java-p7)**

[外链图片转存中...(img-M0IL4CkX-1628418543876)]

![](https://img-blog.csdnimg.cn/img_convert/6f48e39f279720a93602928e293d9b73.png)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值