SpringMVC运行流程 源码分析

本文会分析一下SpringMVC执行的流程,以及源码分析底层实现的原理

SpringMVC流程

请添加图片描述
在这里插入图片描述
在这里插入图片描述

根据以上SpringMVC工作原理图,对其工作流程作如下总结

  1. 用户发送请求至前端控制器DispatcherServlet。

  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。

  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

  4. DispatcherServlet调用HandlerAdapter处理器适配器。

  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

  6. Controller执行完成返回ModelAndView。

  7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。

  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

  9. ViewReslover解析后返回具体View。

  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

  11. DispatcherServlet响应用户。

SpringMVC底层代码流程图:

在这里插入图片描述

SpringMVC底层核心代码块分析

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 {
			// 1、检查文件上传请求
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);

			// Determine handler for the current request. 决定当前请求 用哪个处理器
			// 2、根据当前请求 决定哪个类来处理
			mappedHandler = getHandler(processedRequest);
			// 3、如果没有找到哪个处理器(控制器) 可以处理请求  抛异常
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			// Determine handler adapter for the current request.决定当前请求 用哪个适配器
			// 4、拿到能执行这个类的所有方法的适配器(反射工具) AnnotationMethodHandlerAdapter(注解方法的适配器)
			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 (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)) {
				return;
			}

			// Actually invoke the handler.
			// 5、适配器来执行目标方法:将目标方法完成后的返回值作为视图名 设置保存在ModelAndView中
			// 目标方法无论怎么写,最终适配器执行完成以后 都会将执行后的信息封装成ModelAndView
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}
			// 使用默认的视图名  请求的地址是什么 视图名就是什么
			applyDefaultViewName(request, mv);
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
		// 6、根据方法最终执行完成后封装的ModelAndView;转发到对应的页面,而且ModelAndView可以从请求域中获取
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
	catch (Error err) {
		triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
			}
		}
	}
}

底层方法执行流程:

​ 1、所有的请求过来DispatcherServlet收到请求
​ 2、调用doDispatch()方法进行处理

  • 1)、getHandler() : 根据当前请求地址找到能处理这个请求的目标处理器类(处理器)
    ​ 根据当前请求在HanlderMapping中找到这个请求的映射信息,获取到目标处理器类

  • 2)、getHandlerAdapter() : 根据当前处理器类获取到能执行这个处理器方法的适配器
    根据当前处理器类,找到当前类的HandlerAdapter(适配器)

  • 3)、使用刚才获取的适配器执行目标方法(AnnotationMethodHandlerAdapter)执行目标方法 ​ -

  • 4)、目标方法执行后会返回一个ModelAndView对象 ​ -

  • 5)、根据ModelAndView的信息转发具体的页面,并可以在请求与中取出ModelAndView中的模型数据

3、getHandler()细节:如何根据当前请求就能找到哪个类能来处理

  • getHandler() 会返回目标处理器类的执行链 ​
  • handlerMappings 处理器映射: 里面保存了每一个处理器能处理的那些请求的映射信息 ​
  • handlerMap: ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的handlerMap属性中,下次请求过来 就来看哪个handlerMapping中有这个请求映射信息就行了
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	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;	
}

在这里插入图片描述

​ 4、如何找到目标处理器的适配器。要拿适配器才去执行目标方法

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	for (HandlerAdapter ha : this.handlerAdapters) {
		if (logger.isTraceEnabled()) {
			logger.trace("Testing handler adapter [" + ha + "]");
		}
		// 支持就返回
		if (ha.supports(handler)) {
			return ha;
		}
	}
	throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}


在这里插入图片描述

SpringMVC九大组件

/** 文件上传解析器 */
private MultipartResolver multipartResolver;

/** 区域信息解析器;和国际化有关 */
private LocaleResolver localeResolver;

/** 主题解析器:强大的主题效果更换 */
private ThemeResolver themeResolver;

/** Handler映射信息: handlerMappings*/
private List<HandlerMapping> handlerMappings;

/** Handler的适配器: handlerAdapters*/
private List<HandlerAdapter> handlerAdapters;

/** SpringMVC强大的异常解析功能;异常解析器 */
private List<HandlerExceptionResolver> handlerExceptionResolvers;

/** 视图名称翻译 */
private RequestToViewNameTranslator viewNameTranslator;

/** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;

/** 视图解析器: */
private List<ViewResolver> viewResolvers;
 */
private RequestToViewNameTranslator viewNameTranslator;

/** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;

/** 视图解析器: */
private List<ViewResolver> viewResolvers;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值