SpringMVC源码解析

配置文件

分析SpringMVC之前,首先要看一下配置文件,因为它是我们分析SpringMVC源码的入口。其实里面的重点就是配置了一个ServletContext监听器,他的作用就是监听ServletContext的启动,并且调用重写的contextInitialized方法,这里将会是源码分析的开始。然后就是配置了一个DispatchServlet类型的Servlet,这个大家都熟悉,就是SpringMVC用来处理请求分发和渲染视图的一个Servlet。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <welcome-file-list>
        <welcome-file>login.do</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

WepApplicationContext的创建

当我们在web.xml里面配置某个我们实现的了ServletContextListener接口的监听器后,就会监听ServletContext的启动,在ServletContext启动的时候,就会回调重写的contextInitialized。SpringMVC正是通过这个方法,开始WebApplicationContext的创建(现在还不知道要创建的WebApplicationContext具体是什么类型)
org.springframework.web.context.ContextLoaderListener#contextInitialized

	@Override
	public void contextInitialized(ServletContextEvent event) {
		/**
		 * web.xml配置文件中配置了ContextLoaderListener
		 * 他是ServletContextListener的实现了
		 * 配置了监听器,Servlet容器启动时回先执行他的contextInitialized
		 * 然后才回去执行load on startup的Servlet的init方法
		 */
		initWebApplicationContext(event.getServletContext());
	}

org.springframework.web.context.ContextLoader#initWebApplicationContext

/**
	 * 为给定的servlet context初始化Spring的WebApplicationContext,
	 * 使用构成器提供的WebApplicationContext,
	 * 或者根据 "contextClass"
	 * 和 "contextConfigLocation" 两个context-params
	 * 创建一个新的
	 */
	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		...省略不重要的代码
		try {
			// 创建WebApplicationContext
			// 存储WebApplicationContext到本地实例变量,
			// 保证他在ServletContext关闭的时候也是可用的
			// 当然,同时也会保存一份到servletContext中
			if (this.context == null) {
				// 在这里就会创建WebApplicationContext并返回
				this.context = createWebApplicationContext(servletContext);
			}
			if (this.context instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
				if (!cwac.isActive()) {
					if (cwac.getParent() == null) {
						ApplicationContext parent = loadParentContext(servletContext);
						cwac.setParent(parent);
					}
					/*这里会手动执行WebApplicationContext的refresh方法*/
					configureAndRefreshWebApplicationContext(cwac, servletContext);
				}
			}
			/* 存储WebApplicationContext到servletContext中 */
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

		...省略不重要的代码	
	}

org.springframework.web.context.ContextLoader#createWebApplicationContext

	protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
		/*获取WebApplicationContext的具体类型 */
		Class<?> contextClass = determineContextClass(sc);
		...省略不重要的代码
		/*通过返回的Class对象,反射实例化WebApplicationContext并且强转成ConfigurableWebApplicationContext返回*/
		return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
	}

这里就是确定具体的WebApplicationContext类型的地方
org.springframework.web.context.ContextLoader#determineContextClass

protected Class<?> determineContextClass(ServletContext servletContext) {
		/*如果web.xml中指定了初始化参数ContextClass,就尝试获取此Class*/
		String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
		if (contextClassName != null) {
			try {
				/*获取到了,则返回contextClassName对应的WebApplicationContext的Class对象*/
				return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load custom context class [" + contextClassName + "]", ex);
			}
		}
		else {
			/*没有指定WebApplicationContext类型,则从defaultStrategies中获取默认的,defaultStrategies就是一个Properties的对象*/
			contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
			try {
				/*返回默认的WebApplicationContext的Class对象 */
				return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load default context class [" + contextClassName + "]", ex);
			}
		}
	}

可以看到首先会看看有没有在web.xml中指定初始化化参数ContextClass,这个参数需要指定具体的WebApplicationContext的完整类名,然后根据它加载对应的Class对象。但是我们一般不指定这东西,就是使用默认的,默认就会从Properties类型的对象defaultStrategies当中获取,而defaultStrategies其实是在ContextLoader的静态块中创建

	private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";


	private static final Properties defaultStrategies;

	static {
		try {
			/*在这里就会读取到配置文件ContextLoader.properties中默认的WebApplicationContext类型,并且保存到defaultStrategies中*/
			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
		}
	}

可以看到这里是读取配置文件ContextLoader.properties中配置的文件

# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

可以看到,默认的类型就是XmlWebApplicationContext。通过返回XmlWebApplicationContext的Class对象,反射实例化XmlWebApplicationContext。
创建WebApplicationContext成功后,就会手动执行刷新,就是上面ContextLoader类的initWebApplicationContext中的configureAndRefreshWebApplicationContext(cwac, servletContext);。其实就是执行AbstractApplicationContext中的refresh方法,他是Spring中在ApplicationContext创建的时候,进行BeanDefinition的加载,BeanFactory创建,Bean的创建和保存等等一系列动作的入口。

	protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
		...省略不重要的代码
		/* 把ServletContext设置到WebApplicationContext中 */
		wac.setServletContext(sc);
		
		...省略不重要的代码
		
		/*执行WebApplicationContext的refresh方法,该方法继承于父类AbstractApplicationContext*/
		wac.refresh();
	}

DispatchServlet的初始化

然后就是DispatchServlet的创建,因为web.xml中配置了load-on-startup为1,所以Servlet容器启动后马上启动。Servlet创建后会调用init初始化方法,而DispatchServlet的init的方法在他间接继承的父类HttpServletBean中
org.springframework.web.servlet.HttpServletBean#init

	/**
	 * 将配置参数映射到这个servlet的bean属性上,并调用子类初始化
	 */
	@Override
	public final void init() throws ServletException {
		// 从init参数设置bean属性.
		PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
		if (!pvs.isEmpty()) {
			try {
				BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
				ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
				bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
				initBeanWrapper(bw);
				bw.setPropertyValues(pvs, true);
			}
			catch (BeansException ex) {
				if (logger.isErrorEnabled()) {
					logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
				}
				throw ex;
			}
		}

		// 子类的初始化工作.
		initServletBean();
	}

org.springframework.web.servlet.FrameworkServlet#initServletBean

	@Override
	protected final void initServletBean() throws ServletException {
		...省略不重要的代码
		try {
			/**
			 * 初始化WebApplicationContext, 并保存到DispatchServlet的成员变量中
			 * 这里之所以要这样做,是因为DispatchServlet重载类构造方法,支持通过构造方法参入一个WebApplicationContext
			 * 另外之前创建的WebApplicationContext,是保存到ContextLoader的成员变量和ServletContext中的
			 * DispatchServlet中并没有
			 */
			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();
		}
		catch (ServletException | RuntimeException ex) {
			logger.error("Context initialization failed", ex);
			throw ex;
		}
	...省略不重要的代码
	}

org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext

	protected WebApplicationContext initWebApplicationContext() {
		/*ServletContext中获取WebApplicationContext,就是ContextLoader中创建的WebApplicationContext*/
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;
		// 这里要判断一次啊DispatchServlet中的成员变量webApplicationContext
		// 因为DispatchServlet重载的构造,支持传入WebApplicationContext类型的参数
		if (this.webApplicationContext != null) {
			// 在构造器注入上下文实例,使用它
			wac = this.webApplicationContext;
			if (wac instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
				if (!cwac.isActive()) {
					// 上下文尚未刷新 -> 提供诸如设置父上下文、设置应用程序上下文id等服务
					if (cwac.getParent() == null) {
						// 如果当前的WebApplicationContext对象的parent属性为空,则赋值为rootContext
						cwac.setParent(rootContext);
					}
					/*手动refresh当前的WebApplicationXml,和前面一样,因为是构造方法传入的,还没用refresh */
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		if (wac == null) {
			// 在构建时没有注入上下文实例,看看是否已经在servlet上下文中注册了一个。
			// 如果存在,则假定父上下文(如果有的话)已经设置,
			// 并且用户已经执行了任何初始化,比如设置上下文id
			// 其实就是从ServletContext找到ContextLoader创建的WebApplicationContext
			wac = findWebApplicationContext();
		}
		if (wac == null) {
			// 没有为这个servlet定义上下文实例->创建一个
			wac = createWebApplicationContext(rootContext);
		}

		if (!this.refreshEventReceived) {
			// 要么上下文不是具有刷新支持的可配置applicationcontext,
			// 要么在构建时注入的上下文已经被刷新
			// 在这里手动触发初始化onRefresh方法
			// 会调用到DispatchServlet重写的方法
			synchronized (this.onRefreshMonitor) {
				// 接下来就是分析这里
				onRefresh(wac);
			}
		}

		if (this.publishContext) {
			// 将WebApplicationContext作为servlet上下文属性发布。
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
		}

		return wac;
	}

org.springframework.web.servlet.DispatcherServlet#onRefresh

/**
	 * 这个实现调用{@link #initStrategies}。
	 */
	@Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}

	/**
	 * 初始化这个servlet使用的策略对象。
	 * 可以在子类中重写,以便进一步初始化策略对象。
	 */
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		/* 初始化HandlerMappings */
		initHandlerMappings(context);
		/* 初始化HandlerAdapters */
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		/* 初始化ViewResolvers */
		initViewResolvers(context);
		initFlashMapManager(context);
	}

可以看到,接下来就是初始化DispatchServlet中的各种组件了,比较重要的有HandlerMappings,HandlerAdapters,ViewResolvers。

DispatchServlet重要组件的初始化

org.springframework.web.servlet.DispatcherServlet#initHandlerMappings

/**
	 * 初始化该类使用的处理器映射。
	 * 如果在这个名称空间的BeanFactory中没有定义HandlerMapping bean,
	 * 我们默认使用BeanNameUrlHandlerMapping。
	 */
	private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;
		/*detectAllHandlerMappings 默认true*/
		if (this.detectAllHandlerMappings) {
			// 找到所有ApplicationContext中的HandlerMapping,包括祖先ApplicationContext
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				/*保存所有的HandlerMapping*/
				this.handlerMappings = new ArrayList<>(matchingBeans.values());
				// 对HandlerMapping进行排序.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			/**
			 * 默然情况下,SpringMVC会加载所有实现了HandlerMapping接口的Bean,
			 * 但是也可以让SpringMVC只加载BeanName为handlerMapping的HandlerMapping实现类,
			 * 就是在web.xml配置文件中配置初始化化参数detectAllHandlerMappings为false
			 * 如果没有找到BeanName为handlerMapping的Bean,
			 * 则加载DispatcherServlet.properties配置文件中默认的handlerMappings
			 */
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		...省略不重要的代码

		for (HandlerMapping mapping : this.handlerMappings) {
			if (mapping.usesPathPatterns()) {
				this.parseRequestPath = true;
				break;
			}
		}
	}

org.springframework.web.servlet.DispatcherServlet#initHandlerAdapters

	/**
	 * 初始化该类使用的handleradapter。
	 * 如果在此名称空间的BeanFactory中没有定义HandlerAdapter bean,
	 * 我们默认为SimpleControllerHandlerAdapter。
	 */
	private void initHandlerAdapters(ApplicationContext context) {
		this.handlerAdapters = null;
		/*detectAllHandlerAdapters 默认true*/
		if (this.detectAllHandlerAdapters) {
			// 找到所有ApplicationContext中的HandlerAdapter,包括祖先ApplicationContext.
			Map<String, HandlerAdapter> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
			if (!matchingBeans.isEmpty()) {
				/*保存所有的HandlerAdapter*/
				this.handlerAdapters = new ArrayList<>(matchingBeans.values());
				// 对HandlerAdapter进行排序..
				AnnotationAwareOrderComparator.sort(this.handlerAdapters);
			}
		}
		else {
			/**
			 * 如果在web.xml中初始化参数detectAllHandlerAdapters为false,
			 * 则只在WebApplicationContext中查找名为handlerAdapter的Bean
			 * 如果没有,则使用DispatcherServlet.properties配置文件中默认的的HandlerAdapter
			 */
			try {
				HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
				this.handlerAdapters = Collections.singletonList(ha);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerAdapter later.
			}
		}

		...省略不重要的代码
	}

org.springframework.web.servlet.DispatcherServlet#initViewResolvers

	/**
	 * 初始化该类使用的ViewResolvers。
	 * 如果在BeanFactory中没有为此定义ViewResolver bean
	 * 名称空间,默认为InternalResourceViewResolver。
	 */
	private void initViewResolvers(ApplicationContext context) {
		this.viewResolvers = null;
		/*detectAllViewResolvers 默认true*/
		if (this.detectAllViewResolvers) {
			// 找到所有ApplicationContext中的ViewResolver,包括祖先ApplicationContext.
			Map<String, ViewResolver> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				/*保存所有的ViewResolver*/
				this.viewResolvers = new ArrayList<>(matchingBeans.values());
				// 对ViewResolver进行排序
				AnnotationAwareOrderComparator.sort(this.viewResolvers);
			}
		}
		else {
			/**
			 * 如果在web.xml中初始化参数detectAllViewResolvers为false,
			 * 则只在WebApplicationContext中查找名为viewResolver的Bean
			 * 如果没有,则使用DispatcherServlet.properties配置文件中默认的的ViewResolver
			 */
			try {
				ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
				this.viewResolvers = Collections.singletonList(vr);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default ViewResolver later.
			}
		}
		...省略不重要的代码
	}

DispatchServlet的组件全部初始化完毕后,一切的准备工作就都做好了,接下来就可以正常的处理请求。在此之前先贴上spring-webmvc指定默认组件类型的properties文件DispatcherServlet.properties

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
	org.springframework.web.servlet.function.support.RouterFunctionMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter


org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

DispatchServlet的处理逻辑

	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

	/**
	 * Delegate POST requests to {@link #processRequest}.
	 * @see #doService
	 */
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

可以看到,无论是get请求,或者是post请求,都调用的是processRequest方法来处理请求
org.springframework.web.servlet.FrameworkServlet#processRequest

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			...省略不重要的代码
			doService(request, response);
			...省略不重要的代码
			}

org.springframework.web.servlet.DispatcherServlet#doService

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
			/*doDispatch中就是完整的请求处理过程*/
			doDispatch(request, response);
}

下面就是DispatchServlet真正处理请求的过程了,在继续往下看前,先贴一张DispatchServlet处理请求的完整流程图
在这里插入图片描述

然后对照代码看一下,是否流程完全一样?
org.springframework.web.servlet.DispatcherServlet#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);

				/*根据request寻找对应的mappedHandler,然后获取HandlerExecutionChain*/
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					/*如果没有找到对应的Handler,则通过response返回错误信息*/
					noHandlerFound(processedRequest, response);
					return;
				}

				/*根据当前的mappedHandler的getHandler方法返回的handler(一般就是HandlerMethod,老式用法就是Controller),寻找对应的HandlerAdapter*/
				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方法
				 * 如果其中一个返回false,
				 * 就执行拦截器链所有的拦截器的afterCompletion方法
				 * 然后返回false,然后这里就会return
				 * 正常情况下不进这个分支
				 */
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 处理请求并返回ModelAndView对象.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

				/*如果ModelAndView中没有View,则添加默认的viewName*/
				applyDefaultViewName(processedRequest, mv);
				/*调用各拦截器链上拦截器的postHandler方法*/
				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到View,再渲染jsp,通过response输出页面的过程。 当然最后还会调用拦截器的afterCompletion方法 */
			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);
				}
			}
		}
	}

获取mappedHandler

这里会遍历DispatchSerlet中所有的HandlerMapping,尝试通过request查找对应的handler。handler有可能有不同类型,如果我们平常的那种注解式开发的Controller,就会返回HandlerMethod。但是还用一种方式,就是我们编写的Controller类继承AbstractController,那么这里就会返回Controller。然后把handler和拦截器封装成一个HandlerExecutionChain对象
org.springframework.web.servlet.DispatcherServlet#getHandler

	@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			/*遍历所有的HandlerMapping,直到通过request可以获取到HandlerExecutionChain */
			for (HandlerMapping mapping : this.handlerMappings) {
				/*返回的是HandlerExecutionChain对象,不是想象中的一个HandlerMapping,更不是直接返回handler*/
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler

	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 根据request对象获取handler,其实就是根据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,里面包含了各个拦截器*/
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		...省略不重要的代码

		return executionChain;
	}

下面就是根据request中的url匹配到对应的HandlerMethode的过程

	/**
	 * 查找给定请求的URL路径的handler.
	 * @param request current HTTP request
	 * @return the handler instance, or {@code null} if none found
	 */
	@Override
	@Nullable
	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
		String lookupPath = initLookupPath(request);
		Object handler;
		if (usesPathPatterns()) {
			RequestPath path = ServletRequestPathUtils.getParsedRequestPath(request);
			handler = lookupHandler(path, lookupPath, request);
		}
		else {
			handler = lookupHandler(lookupPath, request);
		}
		if (handler == null) {
			// We need to care for the default handler directly, since we need to
			// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
			Object rawHandler = null;
			if ("/".equals(lookupPath)) {
				rawHandler = getRootHandler();
			}
			if (rawHandler == null) {
				rawHandler = getDefaultHandler();
			}
			if (rawHandler != null) {
				// Bean name or resolved handler?
				if (rawHandler instanceof String) {
					String handlerName = (String) rawHandler;
					rawHandler = obtainApplicationContext().getBean(handlerName);
				}
				validateHandler(rawHandler, request);
				handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
			}
		}
		return handler;
	}

然后把获取到的HandlerMethod封装成HandlerExecutionChain,其实就是添加上各种拦截器

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(request)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

返回的是一个HandlerExecutionChain 对象,然后下面就是HandlerExecutionChain 的成员变量

public class HandlerExecutionChain {
	/*真正的handler,就是HandlerMethod或者Controller*/
	private final Object handler;

	/*存放拦截器的数组*/
	@Nullable
	private HandlerInterceptor[] interceptors;

	/*存放拦截器的list*/
	@Nullable
	private List<HandlerInterceptor> interceptorList;
	...
}

顺便贴一下HandlerMethod中关键的成员变量

public class HandlerMethod {
	// 这个就是我们打了@Controller标签的那个类
	private final Object bean;

	@Nullable
	private final BeanFactory beanFactory;

	private final Class<?> beanType;
	
	// 这个是他要执行的方法
	private final Method method;

	private final Method bridgedMethod;

	// 方法参数
	private final MethodParameter[] parameters;

	@Nullable
	private HttpStatus responseStatus;

	@Nullable
	private String responseStatusReason;

	...
}

根据mappedHandler中的handler对象,获取HandlerAdapter

因为有不同的handler,不同的handler会有不同的接口,所有需要HandlerAdapter去做适配,这里用到的就是设计模式中的适配器模式。拿到了返回的HandlerExecutionChain 对象之后,就会通过里面的handler,获取HandlerAdapter。
org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter

	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			/*遍历所有的HandlerAdapter,直到该HandlerAdapter的supports方法返回true*/
			for (HandlerAdapter adapter : this.handlerAdapters) {
				/*如果adapter的supports方法返回true,代表就是要找的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");
	}

如果handler的类型是HandlerMethoded的话
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports

	@Override
	public final boolean supports(Object handler) {
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

或者handler的类型是老式用法的继承Controller
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#supports

	@Override
	public boolean supports(Object handler) {
		/*当前handler对象时Controller类型,就返回*/
		return (handler instanceof Controller);
	}

处理请求并返回ModelAndView对象

先贴一行DispatchServlet中走到的当前的步骤
org.springframework.web.servlet.DispatcherServlet#doDispatch

// 处理请求并返回ModelAndView对象
// ha就是上面寻找到的HandlerAdapter,mappedHandler.getHandler()返回的是HandlerMethod或者Controller.
// 下面就只分析HandlerMethod的了
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle

	@Override
	@Nullable
	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

下面就是处理请求返回ModelAndView的过程了
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

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

		ModelAndView mav; // 要返回的ModelAndView
		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) {
					// 执行HandlerMethod中的方法,返回ModelAndView
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// 执行HandlerMethod中的方法,返回ModelAndView
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// 执行HandlerMethod中的方法,返回ModelAndView
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		...省略不重要的代码

		return mav;
	}

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

	@Nullable
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		/*封装请求参数webRequest*/
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
			/*根据当前的HandlerMethod创建HandlerMethod的间接子类ServletInvocableHandlerMethod*/
			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 意思就是ModelAndView的容器*/
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			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);
			}
			/*执行请求处理*/
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}
			// 获取并返回ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		/*执行请求处理,继续点进去*/
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		...省略不重要代码
		}

org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest

	@Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		/*获取方法的参数*/
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		/*里面是真的要执行了*/
		return doInvoke(args);
	}

org.springframework.web.method.support.InvocableHandlerMethod#doInvoke

	@Nullable
	protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
			/*利用反射的方式执行方法,就是method.invoke(object, args)*/
			return getBridgedMethod().invoke(getBean(), args);
		}
		catch (IllegalArgumentException ex) {
			...省略不重要代码
		}
		catch (InvocationTargetException ex) {
			...省略不重要代码
		}
	}

请求已经处理完了,还有一步返回ModelAndView
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getModelAndView

	@Nullable
	private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

		modelFactory.updateModel(webRequest, mavContainer);
		if (mavContainer.isRequestHandled()) {
			return null;
		}
		/*从ModelAndViewContainer中获取ModelMap*/
		ModelMap model = mavContainer.getModel();
		/*创建ModelAndView*/
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		...
		/*返回ModelAndView*/
		return mav;
	}

viewResolver通过viewName获取view

现在已经处理完请求,返回了ModelAndView,回到DispatcServlet的doDispatch方法中,进行下一步的分析。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	...
	/*处理ModelAndView到View,再渲染jsp,通过response输出页面的过程 */
	processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	...
}

org.springframework.web.servlet.DispatcherServlet#processDispatchResult

	/**
	 * 处理handler选择和handler调用的结果,该结果要么是ModelAndView,要么是要解析到ModelAndView的异常。
	 */
	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		boolean errorView = false;
		/*发生异常的处理 */
		if (exception != null) {
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// 处理器是否返回一个要渲染的view?
		if (mv != null && !mv.wasCleared()) {
			/*viewResolver通过ModelAndView获取View,进行渲染*/
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		...省略不重要的代码

		if (mappedHandler != null) {
			// 调用该Handler上所有拦截器链中的afterCompletion方法
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

在render方法中就会开始进行,里面将会遍历viewResolvers,尝试通过ModelAndView获取View对象。然后通过View对象的render方法,进行渲染工作。
org.springframework.web.servlet.DispatcherServlet#render

	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		/*通过ModelAndView获取viewName*/
		String viewName = mv.getViewName();
		if (viewName != null) {
			// ModelAndView中包含viewName,则尝试通过viewResolver解析
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// 不需要查找:ModelAndView对象包含实际的视图对象。
			view = mv.getView();
			if (view == null) {
				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
						"View object in servlet with name '" + getServletName() + "'");
			}
		}

		// 委托给view对象进行渲染。
		if (logger.isTraceEnabled()) {
			logger.trace("Rendering view [" + view + "] ");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			/*视图渲染(jsp),然后通过response返回渲染的页面*/
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "]", ex);
			}
			throw ex;
		}
	}

这里就会遍历所有的viewResolver,都尝试获取View,如果获取到了就返回。
org.springframework.web.servlet.DispatcherServlet#resolveViewName

	@Nullable
	protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
			Locale locale, HttpServletRequest request) throws Exception {

		if (this.viewResolvers != null) {
			/*遍历所有的viewResolver*/
			for (ViewResolver viewResolver : this.viewResolvers) {
				/*尝试通过viewResolver解析viewName,看是否能返回view*/
				View view = viewResolver.resolveViewName(viewName, locale);
				/*获取都view不为空,则返回*/
				if (view != null) {
					return view;
				}
			}
		}
		return null;
	}

这里会判断一下是否有缓存,有的话就尝试从缓存中取,没有的话直接创建
org.springframework.web.servlet.view.AbstractCachingViewResolver#resolveViewName

	@Override
	@Nullable
	public View resolveViewName(String viewName, Locale locale) throws Exception {
		if (!isCache()) {
			/*不存在缓存的情况下直接创建view*/
			return createView(viewName, locale);
		}
		else {
			/*否则先尝试从缓存中取*/
			Object cacheKey = getCacheKey(viewName, locale);
			View view = this.viewAccessCache.get(cacheKey);
			if (view == null) {
				synchronized (this.viewCreationCache) {
					view = this.viewCreationCache.get(cacheKey);
					if (view == null) {
						// Ask the subclass to create the View object.
						view = createView(viewName, locale);
						if (view == null && this.cacheUnresolved) {
							view = UNRESOLVED_VIEW;
						}
						if (view != null && this.cacheFilter.filter(view, viewName, locale)) {
							this.viewAccessCache.put(cacheKey, view);
							this.viewCreationCache.put(cacheKey, view);
						}
					}
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace(formatKey(cacheKey) + "served from cache");
				}
			}
			return (view != UNRESOLVED_VIEW ? view : null);
		}
	}

我们直接看createView方法,因为当前viewResolver默认的类型是InternalResourceViewResolver,在上面的DispatcherServlet.properties中可以看到。而InternalResourceViewResolver又继承了UrlBasedViewResolver,createView方法在UrlBasedViewResolver中重写了,所以这里首先会调用类UrlBasedViewResolver的createView方法
org.springframework.web.servlet.view.UrlBasedViewResolver#createView

	@Override
	protected View createView(String viewName, Locale locale) throws Exception {
		// 如果这个解析器不支持处理给定的view,
		// 返回null以传递给链中的下一个解析器
		if (!canHandle(viewName, locale)) {
			return null;
		}

		// "redirect:" 前缀,重定向的处理。
		if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
			String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
			RedirectView view = new RedirectView(redirectUrl,
					isRedirectContextRelative(), isRedirectHttp10Compatible());
			String[] hosts = getRedirectHosts();
			if (hosts != null) {
				view.setHosts(hosts);
			}
			return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
		}

		// "forward:" 前缀,内部转发的处理。
		if (viewName.startsWith(FORWARD_URL_PREFIX)) {
			String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
			InternalResourceView view = new InternalResourceView(forwardUrl);
			return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
		}

		// 否则回到超类实现:调用loadView.
		return super.createView(viewName, locale);
	}

org.springframework.web.servlet.view.AbstractCachingViewResolver#createView
这里除了处理重定向和转发的处理,剩下的就是回调父类AbstractCachingViewResolver的createView方法,然后里面又会调用loadView方法。

	@Nullable
	protected View createView(String viewName, Locale locale) throws Exception {
		return loadView(viewName, locale);
	}

UrlBasedViewResolver重写了loadView方法,所以又会回到UrlBasedViewResolver中,这里就会真正的创建View并返回
org.springframework.web.servlet.view.UrlBasedViewResolver#loadView

	@Override
	protected View loadView(String viewName, Locale locale) throws Exception {
		/* 通过viewName获取View的子类AbstractUrlBasedView */
		AbstractUrlBasedView view = buildView(viewName);
		/* 执行bean的初始化回调方法initializeBean */
		View result = applyLifecycleMethods(viewName, view);
		// 返回view
		return (view.checkResource(locale) ? result : null);
	}

buildView方法会调用InternalResourceViewResolver的buildView,然后又会调用父类UrlBasedViewResolver的buildView方法
org.springframework.web.servlet.view.InternalResourceViewResolver#buildView

	@Override
	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		/*调用UrlBasedViewResolver的buildView方法*/
		InternalResourceView view = (InternalResourceView) super.buildView(viewName);
		if (this.alwaysInclude != null) {
			view.setAlwaysInclude(this.alwaysInclude);
		}
		view.setPreventDispatchLoop(true);
		return view;
	}

buildView方法中会反射实例化一个AbstractUrlBasedView对象,然后对他进行一推的属性设置
org.springframework.web.servlet.view.UrlBasedViewResolver#buildView

	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		Class<?> viewClass = getViewClass();
		Assert.state(viewClass != null, "No view class");

		AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(viewClass);
		/*添加前缀以及后缀*/
		view.setUrl(getPrefix() + viewName + getSuffix());
		view.setAttributesMap(getAttributesMap());

		String contentType = getContentType();
		if (contentType != null) {
			view.setContentType(contentType);
		}

		String requestContextAttribute = getRequestContextAttribute();
		if (requestContextAttribute != null) {
			view.setRequestContextAttribute(requestContextAttribute);
		}

		Boolean exposePathVariables = getExposePathVariables();
		if (exposePathVariables != null) {
			view.setExposePathVariables(exposePathVariables);
		}
		Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
		if (exposeContextBeansAsAttributes != null) {
			view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes);
		}
		String[] exposedContextBeanNames = getExposedContextBeanNames();
		if (exposedContextBeanNames != null) {
			view.setExposedContextBeanNames(exposedContextBeanNames);
		}

		return view;
	}

最后就会返回这个view,然后调用他的render方法

view的渲染

先回到DispatchServlet的render方法,看看我们接下来要看的代码

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	/*视图渲染(jsp),然后通过response返回渲染的页面*/
	view.render(mv.getModelInternal(), request, response);
}

org.springframework.web.servlet.view.AbstractView#render

	/**
	 * 根据指定的模型准备视图,如有必要,将其与静态属性和RequestContext属性合并。
	 * 委托renderMergedOutputModel进行实际的渲染。
	 * @see #renderMergedOutputModel
	 */
	@Override
	public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		if (logger.isDebugEnabled()) {
			logger.debug("View " + formatViewName() +
					", model " + (model != null ? model : Collections.emptyMap()) +
					(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
		}

		/*mergedModel 可以理解为就是jsp中我们可以获取通过JSTL获取到的数据:如${users}*/
		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
		prepareResponse(request, response);
		/*进行实际的渲染,并通过response输出*/
		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
	}

org.springframework.web.servlet.view.InternalResourceView#renderMergedOutputModel

	@Override
	protected void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// 将model object公开为请求属性.
		exposeModelAsRequestAttributes(model, request);

		// 公开helpers作为请求属性, 如果有.
		exposeHelpers(request);

		// 确定请求dispatcher的路径。
		String dispatcherPath = prepareForRendering(request, response);

		// 获取目标资源(通常是一个JSP)的RequestDispatcher。
		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
		if (rd == null) {
			throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
					"]: Check that the corresponding file exists within your web application archive!");
		}

		// 如果已经包含或响应已经提交,则执行include,否则执行forward。
		if (useInclude(request, response)) {
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including [" + getUrl() + "]");
			}
			rd.include(request, response);
		}

		else {
			//注意:转发的资源应该决定content type本身。
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to [" + getUrl() + "]");
			}
			rd.forward(request, response);
		}
	}

rd会转发到一个Servlet中,专门进行jsp的解析,最后把拼装成的html交给response输出到客户端浏览器。

到此为止,源码分析就结束了。

Java配置注册的DispatchServlet

在最开始的时候有说道,DispatchServlet是支持构造器实例化的,并且通过构造器参数的方式传递ApplicationContext。但是上面并没有体现,这里补充一下。

在SpringMVC的官方文档中,有这么一段代码示例

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

意思就是我们实现一个WebApplicationInitializer 接口的实现类,然后重写onStartup。我们在里面创建AnnotationConfigWebApplicationContext,并且制定扫描的配置类如AppConfig.class,调用它的refresh刷新方法,然后new一个DispatcherServlet,把AnnotationConfigWebApplicationContext 传递进去,然后再把DispatchServlet注册到ServletContext 中,然后还有指定指定LoadOnStartup为1,该Servelt接受请求的路径。至此,代码方式的配置就结束了,完全跟web.xml中配置的一模一样。

但问题是他为什么会生效呢?
其实这里涉及到Servlet3.0以后提供的新功能
首先tomcat在启动的时候,会扫描ClassPath路径下有没有META-INF/services/javax.servlet.ServletContainerInitializer这样一个配置文件,以下是spring-web的该配置文件的内容

org.springframework.web.SpringServletContainerInitializer

tomcat扫描到后就是去查看这个类,是否实现了ServletContainerInitializer接口,如果是,就会调用里面重写的onStartup方法。并且tomcat会传递一个Set<Class<?>>类型的集合,里面都是Class对象。而具体传递的Class,由实现了ServletContainerInitializer接口的实现类上的注解@HandlesTypes决定,这个也是Tomcat定的一个规范。

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer

可以看到SpringServletContainerInitializer 实现了ServletContainerInitializer,并且@HandlesTypes的值为WebApplicationInitializer.class,tomcat就会扫描所有类型为WebApplicationInitializer的Class,传递给onStartup方法
org.springframework.web.SpringServletContainerInitializer#onStartup

	@Override
	public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<>();

		if (webAppInitializerClasses != null) {
			// 遍历所有实现了WebApplicationInitializer接口的Class对象
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						// 反射实例化后,添加到initializers
						initializers.add((WebApplicationInitializer)
								ReflectionUtils.accessibleConstructor(waiClass).newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
		for (WebApplicationInitializer initializer : initializers) {
			// 遍历所有的WebApplicationInitializer 对象,调用他的onStartup,并且把ServletContext 对象传递进去
			initializer.onStartup(servletContext);
		}
	}

最后就是调用到Spring官网文档上的那段代码


版权声明:本文为weixin_43889578原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。