SpringMVC执行流程

组件介绍

DispatcherServlet(前端控制器)
-----------核心,接收用户请求,进行请求分发,处理响应结果

HandlerMapping(处理器映射器)
-----------1.根据请求的url对应的处理器。 2. 返回处理器执行链(包含Handler对象以及它对应的拦截器)
HandlerAdapter(处理器适配器)
----------- 调用处理器的处理请求方法,因为实现Controller有不同的方式,所以需要获取对应的适配器 适配器模式
Handler(处理器,又名Controller)
-----------1.根据请求执行业务逻辑 2. 返回ModelAndView对象
ViewResolver(视图解析器)
-----------1.处理视图信息,将逻辑视图转化为真正的物理视图 2. 返回View对象

流程图

在这里插入图片描述

源码解析

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //记录日志
		logRequest(request);
		//属性赋值
		Map<String, Object> attributesSnapshot = null;
		...
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
        ...
		try {
		    //分发请求,doDispatch方法中是核心逻辑
			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);
				}
			}
		}
	}
//分发请求  重要!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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);
				// 获取处理器执行链
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == 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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
                //调用拦截器
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 使用合适的处理器适配器调用处理器,此时会跳转到我们自己写的Controller的方法中,执行后返回ModelAndView对象
				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) {
				// 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);
			}
			//调用视图解析器处理ModelAndView对象
			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);
				}
			}
		}
	}
//返回处理器执行链
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
		    //遍历处理器映射器
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				//如果该处理器映射器能返回处理器执行链,则返回
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}
//返回适合处理这个handler的适配器,返回后,这个适配器用于调用处理器的方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
		    //遍历适配器
			for (HandlerAdapter adapter : this.handlerAdapters) {
			    //如果找到一个支持该handler的适配器,则返回
				if (adapter.supports(handler)) {  
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

执行流程总结

1、浏览器向web服务器(如tomcat)发送一个http请求,web服务器对http请求进行解析。 如果解析后的URL地址如果匹配了Web.xml中的servlet-mapping配置 ,就将请求交给DispatcherServlet处理。
/
2、DispatcherServlet接收到这个请求后,doService方法会接收到封装好的两个参数HttpServletRequest和 HttpServletResponse 。
doService(HttpServletRequest request,HttpServletResponse response)
在doService方法中,先进行日志记录 logRequest(request) ,然后对这个request请求填充一些属性,之后将处理过的request对象传入doDispatch方法中,执行doDispatch方法进行分发请求。
/
doDispatch方法中会调用getHandler方法,这个方法内部,其实是一个对handlerMappings的for循环,每个handlerMapping都通过getHandler方法返回HandlerExecutionChain对象,如果这个对象不为null,说明获取成功,将得到的处理器执行链return给DispatcherServlet。在处理器执行链中包含Handler对象以及它对应的拦截器。
/
3、DispatcherServlet将得到的处理器执行链中的Handler对象传入getHandlerAdapter方法中,
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler())
这个方法其实也是个对handlerAdapters的for循环,如果某个handlerAdapters适配传入的Handler对象,则返回该handlerAdapters
判断是否适配:supports方法里其实只是通过 instanceof进行判断
SimpleServletHandlerAdapter: handler instanceof Servlet
HttpRequestHandlerAdapter: handler instanceof HttpRequestHandler

/
4、开始执行Handler
ha.handle(processedRequest, response, mappedHandler.getHandler())
Handler执行完毕后返回一个ModelAndView对象给DispatcherServlet。
/
6、这个ModleAndView只是一个逻辑视图,并不是真正的视图,DispatcherServlet通过ViewResolver视图解析器将逻辑视图转化为真正的物理视图(通俗理解为将视图名称补全,如加上路径前缀,加上.jsp后缀,能指向实际的视图)。
/
7、DispatcherServlet通过Model将ModelAndView中得到的处数据解析后用于渲染视图。将得到的最终视图View对象通过http响应返回客户端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值