springmvc 执行流程

springmvc 执行流程

img

浏览器请求地址:localhost:8080/hello

1、请求经过前置控制器(DispatchServlet)

DispatchServlet 在服务启动的时候创建 (就是你的web.xml配置的)

  <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置初始配置化文件,前面contextConfigLocation看情况二选一 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:config/spring-mvc.xml</param-value>
        </init-param>
        <!-- 启动加载一次 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

并进行一些初始化 (initHandlerMappings 、initHandlerAdapters、initViewResolvers这三个看着是不是很熟悉)

	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}

DispatchServlet其实就是对Servle进行的拓展:DispatcherServlet 继承FrameworkServlet,FrameworkServlet继承HttpServletBean,HttpServletBean 继承httpServlet。DispatcherServlet 中重写了FrameworkServlet的doService方法:

其中的doDispatch(request, response)方法就是springMVC的核心流程

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		//日志 
    	// ... 填充属性
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
		try {
            // 这是就是springmvc的核心流程
			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);
				}
			}
		}
	}

2 DispatchServlet 将请求打到处理器映射器HandlerMapping,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zUDZEcd1-1656647671845)(C:\Users\Administrator.IWDNDRD3NDNEC2F\AppData\Roaming\Typora\typora-user-images\image-20220701111831072.png)]

HandlerMapping的主要职责就是解析url,找到对应的控制器(controller),HandlerMapping就是一系列的map,初始化时存储url和controller的映射关系。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-giFdu1SV-1656647671847)(C:\Users\Administrator.IWDNDRD3NDNEC2F\AppData\Roaming\Typora\typora-user-images\image-20220701110944928.png)]

通常我们写的controller都在RequestMappingHandlerMapping中,其中有的三个map[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zUlD77Um-1656647671847)(C:\Users\Administrator.IWDNDRD3NDNEC2F\AppData\Roaming\Typora\typora-user-images\image-20220701111226122.png)]

urlmap存储的是url的关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6GVlBZmu-1656647671848)(C:\Users\Administrator.IWDNDRD3NDNEC2F\AppData\Roaming\Typora\typora-user-images\image-20220701111309183.png)]

handlerMethods 中是方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-azwR4Fdi-1656647671848)(C:\Users\Administrator.IWDNDRD3NDNEC2F\AppData\Roaming\Typora\typora-user-images\image-20220701111547427.png)]

HandlerMapping返回的是HandlerExecutionChain(包括处理器和拦截器)

3 DispatchServlet 拿到handel后,交给处理器适配器HandlerAdapter处理,适配器顾名思义采用的是适配器的模式,为什么需要适配器呢?适配器的处理对象是处理器,因为处理器种类有很多,需要适配器去适配,找到对应的适配器后即可通过反射的方式执行方法接口。

4 处理器处理完成后 返回给DispatchServlet 的ModelAndVIew,DispatchServlet 拿到ModelAndVIew交给视图解析器

5 渲染

源码:

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

				// 根据url 获取处理器(遍历mapping)
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// 根据处理器获取适配器
				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;
				}

				// 反射调用方法 返回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;
			}
            // 异常处理和渲染页面。
			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);
				}
			}
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值