Spring源码分析(四)SpringMVC

文章目录

  • ContextLoaderListener
  • DispatcherServlet
    • 初始化
    • 九大组件
      • MultipartResolver
      • LocaleResolver
      • ThemeResolver
      • HandlerMapping
        • 初始化
          • BeanNameUrlHandlerMapping
          • RequestMappingHandlerMapping
        • 获取HandlerExecutionChain
          • BeanNameUrlHandlerMapping
          • RequestMappingHandlerMapping
      • HandlerAdapter
        • 初始化
          • SimpleControllerHandlerAdapter
          • RequestMappingHandlerAdapter
            • HandlerMethodArgumentResolver
            • HandlerMethodReturnValueHandler
        • handler执行
          • SimpleControllerHandlerAdapter
          • RequestMappingHandlerAdapter
      • HandlerExceptionResolver
        • ExceptionHandlerExceptionResolver
          • 初始化
          • 异常处理
      • RequestToViewNameTranslator
      • ViewResolver
      • FlashMapManager
    • 访问请求

   ContextLoaderListener位于spring-web中,主要用来为其他Web框架(如Structs框架)提供Spring的核心功能(如IOC等);DispatcherServlet位于spring-webmvc中,同时具有Spring的核心功能以及Web功能,DispatcherServlet也可以与ContextLoaderListener进行集成(将ContextLoaderListener的ApplicationContext作为DispatcherServlet的ApplicationContext的父ApplicationContext),但个人更喜欢单独使用DispatcherServlet(运行过程中可能会因为ApplicationContext的继承关系而埋下许多坑)。

ContextLoaderListener

// ContextLoaderListener用于在Servlet容器启动时,创建一个全局可发现的ApplicationContext
// ContextLoaderListener继承自ContextLoader,创建ApplicationContext并发布到全局(保存为ServletContext的属性)就是全由该父类实现的
// 为了能在Servlet容器启动时执行程序,所以ContextLoaderListener实现了ServletContextListener接口
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
	public void contextInitialized(ServletContextEvent event) {
		initWebApplicationContext(event.getServletContext());
	}
}

// 负责创建一个ApplicationContext
public class ContextLoader {
	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
			throw new IllegalStateException(...);
		}

		long startTime = System.currentTimeMillis();

		if (this.context == null) {
			// 先通过determineContextClass(...)获取ApplicationContext的具体实现类,然后通过该类创建实例
			this.context = createWebApplicationContext(servletContext);
		}
		
		if (this.context instanceof ConfigurableWebApplicationContext) {
			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
			if (!cwac.isActive()) {
				if (cwac.getParent() == null) {
					// loadParentContext(...)默认返回null,可由子类重写(实际应用中并没有重写)
					ApplicationContext parent = loadParentContext(servletContext);
					cwac.setParent(parent);
				}
				// 配置和刷新上下文
				configureAndRefreshWebApplicationContext(cwac, servletContext);
			}
		}
			
		// 将创建的上下文保存在ServletContext中,这样Web应用的其他地方就可以通过ServletContext获取此上下文
		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

		ClassLoader ccl = Thread.currentThread().getContextClassLoader();
		if (ccl == ContextLoader.class.getClassLoader()) {
			currentContext = this.context;
		} else if (ccl != null) {
			currentContextPerThread.put(ccl, this.context);
		}

		return this.context;
	}

	// 决定ApplicationContext的具体实现类
	protected Class<?> determineContextClass(ServletContext servletContext) {
		// 获取ServletContext中key为"contextClass"的参数作为ApplicationContext的具体实现类
		String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
		if (contextClassName != null) {
			return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
		} else {
			// defaultStrategies是spring-web包下org/springframework/web/context/ContextLoader.properties文件加载而成的Properties(该类的静态块中完成了这一加载过程)
			// org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
			// 所以ApplicationContext的具体实现类为XmlWebApplicationContext
			contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
			return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
		}
	}

	// 配置和刷新上下文
	protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
		// AbstractApplicationContext的id属性默认是ObjectUtils.identityToString(this)
		// 如果id还是默认id,那么就重新设置id
		// 先通过ServletContext中key为"contextConfigLocation"的参数值来设置id
		// 如果ServletContext中不包含该key,就用org.springframework.web.context.WebApplicationContext:ServletContext的路径
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
			if (idParam != null) {
				wac.setId(idParam);
			} else {
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
						ObjectUtils.getDisplayString(sc.getContextPath()));
			}
		}

		// 将ServletContext保存在ApplicationContext中,便于后面使用
		wac.setServletContext(sc);

		// 获取ServletContext中key为"contextConfigLocation"的参数用来作为配置的XML的路径
		String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
		if (configLocationParam != null) {
			wac.setConfigLocation(configLocationParam);
		}
		
		// 默认是StandardServletEnvironment
		ConfigurableEnvironment env = wac.getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
		}

		// 在refresh()之前执行ApplicationContextInitializer.initialize(...),通常用于对ApplicationContext进行自定义的初始化
		customizeContext(sc, wac);
		
		// 刷新ApplicationContext
		wac.refresh();
	}

	// 执行所有注册的ApplicationContextInitializer的initialize(...)方法
	protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
		// 决定有哪些类型的Class
		List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses = determineContextInitializerClasses(sc);

		// 将已确定的ApplicationContextInitializer类实例化并进行注册
		for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {
			// 获取ApplicationContextInitializer的类型参数T所代表的Class
			Class<?> initializerContextClass = GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
			if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) {
				throw new ApplicationContextException(...);
			}
			this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass));
		}

		// 对所有已注册的ApplicationContextInitializer进行排序,然后依次调用其initialize(...)方法
		AnnotationAwareOrderComparator.sort(this.contextInitializers);
		for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
			initializer.initialize(wac);
		}
	}

	// 决定哪些ApplicationContextInitializer需要被注册
	protected List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>
			determineContextInitializerClasses(ServletContext servletContext) {
		// 用于保存所有注册的ApplicationContextInitializer类型
		List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> classes = new ArrayList<>();

		// ServletContext中key为"globalInitializerClasses"的参数所配置的ApplicationContextInitializer的子类全名
		// 多个类全名用','、';'或'\t\n'分割
		String globalClassNames = servletContext.getInitParameter(GLOBAL_INITIALIZER_CLASSES_PARAM);
		if (globalClassNames != null) {
			for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
				// loadInitializerClass(...)根据类全名加载出Class对象,这必须是ApplicationContextInitializer的子类
				classes.add(loadInitializerClass(className));
			}
		}

		// ServletContext中key为"contextInitializerClasses"的参数所配置的ApplicationContextInitializer的子类全名
		// 多个类全名用','、';'或'\t\n'分割
		String localClassNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
		if (localClassNames != null) {
			for (String className : StringUtils.tokenizeToStringArray(localClassNames, INIT_PARAM_DELIMITERS)) {
				classes.add(loadInitializerClass(className));
			}
		}

		return classes;
	}
}

DispatcherServlet

  DispatcherServlet(WEB功能) -> FrameworkServlet(容器功能) -> HttpServletBean(配置功能) -> HttpServlet -> GenericServlet -> Servlet

初始化

public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
	// Servlet初始化入口
	public final void init() throws ServletException {
		// 将Servlet配置的所有InitParameter封装成PropertyValues,requiredProperties(一个字符串集合)中所有的key必须有相应的InitParameter
		// 将当前Servlet对象(实际上是DispatcherServlet对象)中的属性用pvs进行设置,也就是用InitParameter来设置DispatcherServlet的属性
		PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
		if (!pvs.isEmpty()) {
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);
		}

		// 初始化ApplicationContext与Servlet
		initServletBean();
	}
}

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
	protected final void initServletBean() throws ServletException {
		long startTime = System.currentTimeMillis();

		// 初始化WebApplicationContext
		this.webApplicationContext = initWebApplicationContext();

		// 默认为空方法,供子类扩展,实际上到DispatcherServlet也没有扩展该方法
		initFrameworkServlet();
	}

	protected WebApplicationContext initWebApplicationContext() {
		// 从ServletContext中获取ApplicationContext(ContextLoaderListener在ServletContext中设置了ApplicationContext)
		// 实际上调用servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)
		WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;

		// 如果当前Servlet关联的webApplicationContext不为空,那么设置其双亲ApplicationContext并对其进行配置和刷新
		if (this.webApplicationContext != null) {
			wac = this.webApplicationContext;
			if (wac instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
				if (!cwac.isActive()) {
					if (cwac.getParent() == null) {
						cwac.setParent(rootContext);
					}
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		
		if (wac == null) {
			// 实际上调用servletContext.getAttribute(attributName)获取ApplicationContext
			// attributeName由FrameworkServlet.contextAttribute属性提供(默认为null)
			wac = findWebApplicationContext();
		}
		
		// 通常DispatcherServlet在启动时会进入此分支,在此处创建ApplicationContext
		if (wac == null) {
			// 创建ApplicationContext并以rootContext作为父ApplicationContext
			wac = createWebApplicationContext(rootContext);
		}

		// onRefresh(...)在DispatcherServlet中实现,负责完成Spring的Web功能的初始化
		// this.refreshEventReceived表示是否已经完成了Spring的Web功能的初始化
		if (!this.refreshEventReceived) {
			synchronized (this.onRefreshMonitor) {
				onRefresh(wac);
			}
		}

		// this.publishContext默认为true,将ApplicationContext发布,以便其他地方可以通过ServletContext来获取该ApplicationContext
		if (this.publishContext) {
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
		}

		return wac;
	}

	// 创建WebApplicationContext
	protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
		// 获取需要实例化的ApplicationContext类型并用之进行实例化
		// 默认ApplicationContext类型为FrameworkServlet.DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class
		Class<?> contextClass = getContextClass();
		ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

		wac.setEnvironment(getEnvironment());
		wac.setParent(parent);

		// 设置WebApplicationContext的XML配置文件的位置,其值来自contextConfigLocation属性,属性可以通过Servlet配置的InitParameter配置
		String configLocation = getContextConfigLocation();
		if (configLocation != null) {
			wac.setConfigLocation(configLocation);
		}

		// 配置和刷新上下文
		configureAndRefreshWebApplicationContext(wac);

		return wac;
	}
	
	protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
		// 设置ApplicationContext的id,与ContextLoader的configureAndRefreshWebApplicationContext方法类似
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			if (this.contextId != null) {
				wac.setId(this.contextId);
			} else {
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
						ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
			}
		}

		wac.setServletContext(getServletContext());
		wac.setServletConfig(getServletConfig());
		wac.setNamespace(getNamespace());
		
		// 注册一个ApplicationListener,在后面调用wac.refresh()时会发布监听事件,那时会回调SourceFilteringListener.onApplicationEvent(...)方法
		// SourceFilteringListener.onApplicationEvent(...)直接调用了第二个构造参数(即ContextRefreshListener)的onApplicationEvent(...)方法
		// ContextRefreshListener.onApplicationEvent(...)直接调用了Servlet实现类的onRefresh(...)方法
		// DispatcherServlet的onRefresh(...)方法完成了Spring的Web功能的初始化
		wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

		// 默认是StandardServletEnvironment
		ConfigurableEnvironment env = wac.getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
		}

		// 默认为空函数,提供给子类扩展(实际上到DispatcherServlet也没有进行扩展)
		postProcessWebApplicationContext(wac);

		// 在refresh()之前执行ApplicationContextInitializer.initialize(...),通常用于对ApplicationContext进行自定义的初始化
		// 与ContextLoader的customizeContext(...)方法类似
		applyInitializers(wac);

		// 刷新上下文
		wac.refresh();
	}

	// 执行所有注册的ApplicationContextInitializer的initialize(...)方法
	protected void applyInitializers(ConfigurableApplicationContext wac) {
		// ServletContext中key为"globalInitializerClasses"的参数所配置的ApplicationContextInitializer的子类全名
		// 多个类全名用','、';'或'\t\n'分割
		String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM);
		if (globalClassNames != null) {
			for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
				// loadInitializer(...)根据类全名进行实例化
				this.contextInitializers.add(loadInitializer(className, wac));
			}
		}

		// contextInitializerClasses成员变量所代表的ApplicationContextInitializer的子类全名,属性可以通过Servlet配置的InitParameter配置
		// 多个类全名用','、';'或'\t\n'分割
		if (this.contextInitializerClasses != null) {
			for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) {
				this.contextInitializers.add(loadInitializer(className, wac));
			}
		}

		// 对所有已注册的ApplicationContextInitializer进行排序,然后依次调用其initialize(...)方法
		AnnotationAwareOrderComparator.sort(this.contextInitializers);
		for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
			initializer.initialize(wac);
		}
	}
}

// 该类主要完成了Spring的Web功能
public class DispatcherServlet extends FrameworkServlet {
	// Spring的Web功能的初始化
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}
	
	// 初始化spirng-mvc九大组件  
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}	
}

九大组件

  SpringMVC大九组件的初始化,基本都使用了相同的套路,除了文件上传组件默认为null以外,其他组件最终都通过DispatcherServlet.getDefaultStrategies(…)来获取默认值(通过spring-webmvc包下org/springframework/web/servlet目录中的DispatcherServlet.properties来进行配置,不同Spring版本可以通过该配置来进行组件功能的扩展)。可以通过向AppicationContext中注册bean的方式来覆盖默认组件。

public class DispatcherServlet extends FrameworkServlet {
	// 其实就是调用getDefaultStrategies(...)方法,但是将列表转换为单个元素的对象,也就是说列表必须有且仅有一个元素
	protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
		List<T> strategies = getDefaultStrategies(context, strategyInterface);
		if (strategies.size() != 1) {
			throw new BeanInitializationException(...);
		}
		return strategies.get(0);
	}

	// 获取spring-webmvc包下org/springframework/web/servlet目录中DispatcherServlet.properties属性文件中,
	// key为strategyInterface全类名对应的value(value为strategyInterface的实现类的全类名,多个全类名用','分割)实例化后的列表
	// 如果DispatcherServlet.properties中没有对应的key,那么返回一个空列表
	protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
		// Properties对象defaultStrategies会在类的静态块中初始化,
		// 由spring-webmvc包下org/springframework/web/servlet目录中的DispatcherServlet.properties文件加载而来
		// 如该文件中保存了如下key-value
		// org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
		// org.springframework.web.servlet.HandlerMapping=org...BeanNameUrlHandlerMapping,org...RequestMappingHandlerMapping
		String key = strategyInterface.getName();
		String value = defaultStrategies.getProperty(key);
		
		if (value == null) {
			// 如果没有配置相应strategyInterface的实现类,返回空列表
			return new LinkedList<>();
		} else {
			// 将','分割的多个类全名解析为数组格式
			String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
			List<T> strategies = new ArrayList<>(classNames.length);
			// 将配置的类实例化后放入列表并返回
			for (String className : classNames) {
				Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
				// 根据clazz构建一个原型模式的RootBeanDefinition
				// 并调用ApplicationContext中BeanFactory的createBean(...)方法创建对象,该过程会执行创建Bean的扩展(包括属性注入等)
				Object strategy = createDefaultStrategy(context, clazz);
				strategies.add((T) strategy);
			}
			return strategies;
		} 
	}	
}	

MultipartResolver

  该组件用来将上传文件的请求对象转换为MultipartHttpServletRequest类型,从而实现文件上传功能,默认情况下未注册该组件。可以向容器注册一个名为"multipartResolver"的bean来进行该组件的注册。

  spring-mvc中提供的实现类有:

  • CommonsMultipartResolver:该类依赖于commons-fileupload包,所以需要导入该包
  • StandardServletMultipartResolver:
public interface MultipartResolver {
	// 判断请求是否是文件上传请求(通常是判断请求的ContextType是否是以"multipart/"开头)
	boolean isMultipart(HttpServletRequest request);
	// 将文件上传的请求封装成MultipartHttpServletRequest,该类型的请求提供了许多关于获取上传的文件的接口
	MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
	// 完成文件上传后的清理工作
	void cleanupMultipart(MultipartHttpServletRequest request);
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取名为"multipartResolver"的Bean作为Web应用的MultipartResolver,默认为null
	private void initMultipartResolver(ApplicationContext context) {
		try {
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
		} catch (NoSuchBeanDefinitionException ex) {
			this.multipartResolver = null;
		}
	}
}	

LocaleResolver

  该组件主要用于国际化功能,通过解析请求得到Locale对象,默认使用AcceptHeaderLocaleResolver(这与spring-mvc的版本有关,后面的默认值也与版本有关,以下不再说明)。可以向容器注册一个名为"localeResolver"的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • FixedLocaleResolver:获取默认Locale(可以通过setDefaultLocale(…)设置默认Locale),未设置默认Locale时得到Locale.getDefault()
  • AcceptHeaderLocaleResolver:从请求中获取Locale,即request.getLocale()(实际就是根据请求头"Accept-Language"的值来生成Locale),无法通过request.getLocale()获取Locale就得到默认Locale(可以通过setDefaultLocale(…)设置默认Locale)
  • SessionLocaleResolver:从session中获取Locale(可以通过setLocale(…)设置session作用范围的Locale),如果无法从session中获取Locale,那么获取默认的Locale(可以通过setDefaultLocale(…)设置默认Locale),如果依然无法获取到Locale,通过request.getLocale()获取。
  • CookieLocaleResolver:从cookie中获取Locale(可以通过setLocale(…)设置cookie作用范围的Locale)
public interface LocaleResolver {
	// 解析请求得到Locale对象
	Locale resolveLocale(HttpServletRequest request);
	
	void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale);
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取名为"localeResolver"的Bean作为Web应用的LocaleResolver
	private void initLocaleResolver(ApplicationContext context) {
		try {
			this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
		} catch (NoSuchBeanDefinitionException ex) {
			this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
		}
	}
}

ThemeResolver

  该组件主要用于主题功能,通过解析请求得到主题名,默认使用FixedThemeResolver。可以向容器注册一个名为"themeResolver"的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • FixedThemeResolver:获取默认的主题名,默认主题名初始值为"theme",可以通过setDefaultThemeName(…)重新设置
  • CookieThemeResolver:从cookie中获取主题名,可以通过setThemeName(…)设置cookie作用范围的主题名,如果无法从cookie中获取主题名,那么获取默认的主题名(默认主题名初始值与设置方式同FixedThemeResolver)。
  • SessionThemeResolver:从session中获取主题名,可以通过setThemeName(…)设置session作用范围的主题名,如果无法从session中获取主题名,那么获取默认的主题名(默认主题名初始值与设置方式同FixedThemeResolver)。
public interface ThemeResolver {
	// 解析请求得到主题名
	String resolveThemeName(HttpServletRequest request);
	
	void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取名为"themeResolver"的Bean作为Web应用的ThemeResolver
	private void initThemeResolver(ApplicationContext context) {
		try {
			this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);
		} catch (NoSuchBeanDefinitionException ex) {
			this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);
		}
	}
}

HandlerMapping

  该组件会根据请求(一般是请求的url)来获取匹配的拦截器和对请求进行处理的对象(该对象如何处理请求是由HandlerAdapter决定的),默认使用了BeanNameUrlHandlerMapping、RequestMappingHandlerMapping、RouterFunctionMapping。可以向容器注册一个或多个HandlerMapping实现类的bean来覆盖默认组件。当客户端发起请求时,会依次调用这些HandlerMapping的getHandler(…)方法,直到获取HandlerExecutionChain为止。

  spring-mvc中提供的实现类有:

  • BeanNameUrlHandlerMapping:请求到来时,根据Controller的beanName匹配url(Controller必须是实现了Controller的接口,且在容器中已注册的bean),并调用Controller实现的handleRequest(…)方法
  • RequestMappingHandlerMapping:实现了InitializingBean接口,在其afterPropertiesSet(…)方法中完成了初始化。根据Controller及其方法的RequestMapping注解来匹配url(Controller必须被@Controller或@RequestMapping标记,且在容器中已注册的bean)。当下的MVC编程几乎都是基于该HandlerMapping的,下面也只对该类做源码分析
  • RouterFunctionMapping
  • SimpleUrlHandlerMapping
public interface HandlerMapping {
	// 根据请求获取执行链(可以包括多个拦截器,必须包含一个Handler)
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取所有HandlerMapping实现类或名为"handlerMapping"的Bean作为Web应用的List
	private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;

		// this.detectAllHandlerMappings默认为true
		if (this.detectAllHandlerMappings) {
			// 从ApplicationContext中获取所有HandlerMapping实现类的Bean,排序后作为Web应用的List
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<>(matchingBeans.values());
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		} else {
			try {
				// 从ApplicationContext中获取名为"handlerMapping"的Bean作为Web应用的List
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			} catch (NoSuchBeanDefinitionException ex) {
				// 什么也不做
			}
		}

		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
		}
	}
}
初始化

  几乎所有的HandlerMapping都继承了AbstractHandlerMapping,而AbstractHandlerMapping实现了ApplicationContextAware接口,所以setApplicationContext(…)方法是初始化的入口
  更详细的继承关系:AbstractHandlerMapping -> WebApplicationObjectSupport -> ApplicationObjectSupport

public abstract class ApplicationObjectSupport implements ApplicationContextAware {
	public final void setApplicationContext(@Nullable ApplicationContext context) throws BeansException {
		if (context == null && !isContextRequired()) { // context通常不为null,所以不会进入该分支
			this.applicationContext = null;
			this.messageSourceAccessor = null;
		} else if (this.applicationContext == null) { // 通常会进入此分支
			// 判断ApplicationContext是不是期望的类型,如果不是抛出异常
			if (!requiredContextClass().isInstance(context)) {
				throw new ApplicationContextException(...);
			}
			this.applicationContext = context;
			this.messageSourceAccessor = new MessageSourceAccessor(context);
			// 由子类实现初始化,实际在WebApplicationObjectSupport进行了实现
			initApplicationContext(context);
		} else { // 避免重复初始化
			if (this.applicationContext != context) {
				throw new ApplicationContextException(...);
			}
		}
	}	
}

public abstract class WebApplicationObjectSupport extends ApplicationObjectSupport {
	protected void initApplicationContext(ApplicationContext context) {
		// 调用父类ApplicationObjectSupport的initApplicationContext(context)
		// 父类的方法却直接调用了initApplicationContext()方法,AbstractHandlerMapping实现了该方法
		super.initApplicationContext(context);
		// 如果是Web应用,初始化Servlet相关,个人觉得对于Handler的注册由子类实现initServletContext(...)方法比较恰当
		// 然而该方法在springmvc默认都是空方法
		if (this.servletContext == null && context instanceof WebApplicationContext) {
			this.servletContext = ((WebApplicationContext) context).getServletContext();
			if (this.servletContext != null) {
				initServletContext(this.servletContext);
			}
		}
	}
}	

public abstract class AbstractHandlerMapping {
	protected void initApplicationContext() throws BeansException {
		// 实际上是个空方法,什么也没有干
		extendInterceptors(this.interceptors);
		// 将所有MappedInterceptor类型的Bean注册进adaptedInterceptors
		detectMappedInterceptors(this.adaptedInterceptors);
		// 将this.interceptors变量中的拦截器也注册进adaptedInterceptors
		initInterceptors();
	}
}
BeanNameUrlHandlerMapping

  BeanNameUrlHandlerMapping继承了AbstractMethodMapping,实现了公用功能的初始化,而且重写了初始化过程中提供的扩展接口,从而实现Handler的初始化。
  BeanNameUrlHandlerMapping -> AbstractDetectingUrlHandlerMapping -> AbstractUrlHandlerMapping

public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {
	public void initApplicationContext() throws ApplicationContextException {
		// 确保父类的功能能够实现(初始化拦截器)
		super.initApplicationContext();
		// 初始化Handler
		detectHandlers();
	}

	protected void detectHandlers() throws BeansException {
		ApplicationContext applicationContext = obtainApplicationContext();
		// this.detectHandlersInAncestorContexts默认为false,所以不会获取祖先上下文中的beanName
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		for (String beanName : beanNames) {
			// 根据beanName来决定url,由子类BeanNameUrlHandlerMapping实现
			String[] urls = determineUrlsForHandler(beanName);
			if (!ObjectUtils.isEmpty(urls)) {
				// 分别将所有的url分别和相应的bean绑定
				registerHandler(urls, beanName);
			}
		}
	}
}	

public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
	// 将beanName对应bean以"/"开头的ID和所有别名作为urls
	protected String[] determineUrlsForHandler(String beanName) {
		List<String> urls = new ArrayList<>();
		if (beanName.startsWith("/")) {
			urls.add(beanName);
		}
		String[] aliases = obtainApplicationContext().getAliases(beanName);
		for (String alias : aliases) {
			if (alias.startsWith("/")) {
				urls.add(alias);
			}
		}
		return StringUtils.toStringArray(urls);
	}
}
RequestMappingHandlerMapping

  RequestMappingHandlerMapping不但继承了AbstractMethodMapping,实现了公用功能的初始化,还通过实现InitializingBean接口,来完成Handler的初始化。
  RequestMappingHandlerMapping -> RequestMappingInfoHandlerMapping -> AbstractHandlerMapping

public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping {
	public void afterPropertiesSet() {
		this.config = new RequestMappingInfo.BuilderConfiguration();
		// UrlPathHelper主要用于对url的编解码,从请求中获取url等
		this.config.setUrlPathHelper(getUrlPathHelper());
		// 用于请求的匹配,获取url路径中的参数等(如/ab/{param}中的param)
		this.config.setPathMatcher(getPathMatcher());
		this.config.setSuffixPatternMatch(useSuffixPatternMatch());
		this.config.setTrailingSlashMatch(useTrailingSlashMatch());
		this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
		this.config.setContentNegotiationManager(getContentNegotiationManager());

		// 该方法在AbstractHandlerMethodMapping中实现,用于完成handler的注册
		super.afterPropertiesSet();
	}

	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		// 获取方法的@RequestMapping注解,会根据@RequestMapping注解的各种属性来初始化RequestMappingInfo
		RequestMappingInfo info = createRequestMappingInfo(method);
		if (info != null) {
			// 获取类上的@RequestMapping注解
			RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
			if (typeInfo != null) {
				// 将两个注解进行合并
				info = typeInfo.combine(info);
			}
			// 添加默认的前缀
			String prefix = getPathPrefix(handlerType);
			if (prefix != null) {
				info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
			}
		}
		return info;
	}

	// 初始化跨域
	protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
		HandlerMethod handlerMethod = createHandlerMethod(handler, method);
		Class<?> beanType = handlerMethod.getBeanType();
		CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class);
		CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);

		// 如果类与方法都未被CrossOrigin注解标记,那么就不支持跨域请求
		if (typeAnnotation == null && methodAnnotation == null) {
			return null;
		}

		// 用类上的CrossOrigin注解更新配置,再用方法上的CrossOrigin注解更新配置(聚集类型会合并)
		CorsConfiguration config = new CorsConfiguration();
		updateCorsConfig(config, typeAnnotation);
		updateCorsConfig(config, methodAnnotation);

		// 如果config的allowedMethod为空,那么用mapping支持的请求方法更新它
		if (CollectionUtils.isEmpty(config.getAllowedMethods())) {
			for (RequestMethod allowedMethod : mappingInfo.getMethodsCondition().getMethods()) {
				config.addAllowedMethod(allowedMethod.name());
			}
		}
		
		// 配置默认值
		return config.applyPermitDefaultValues();
	}
}	

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
	// 只是作为回调的钩子,具体工作转交给initHandlerMethods()来完成
	public void afterPropertiesSet() {
		initHandlerMethods();
	}

	protected void initHandlerMethods() {
		// getCandidateBeanNames()用于获取ApplicationContext中注册的所有bean的ID
		// this.detectHandlerMethodsInAncestorContexts决定是否包含组件ApplicationContext中注册的bean,默认为false,即不包括
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				// 注册Handler,实际上Handler是一个方法
				processCandidateBean(beanName);
			}
		}
		
		// 在handler注册后处理,由子类实现,实际上只是打印了一些日志,没有做其他有意义的事
		handlerMethodsInitialized(getHandlerMethods());
	}

	protected void processCandidateBean(String beanName) {
		Class<?> beanType = obtainApplicationContext().getType(beanName);
		// 根据类(或其父类,以及代理的原始类)是否被@Controller或@RequestMapping(或被其标记的注解)标记来判断当前bean是否是一个Controller
		// 只有Controller的方法才有可能成为Handler
		if (beanType != null && isHandler(beanType)) {
			detectHandlerMethods(beanName);
		}
	}

	protected void detectHandlerMethods(Object handler) {
		// 如果是String类型,那么表示beanName,通过ApplicationContext来获取bean的类型
		// 如果不是String类型,直接获取其类型
		Class<?> handlerType = (handler instanceof String ?
				obtainApplicationContext().getType((String) handler) : handler.getClass());

		if (handlerType != null) {
			// 如果是使用代理类,那么这里获取原始类型
			Class<?> userType = ClassUtils.getUserClass(handlerType);

			// 获取Method及其配置(RequestMapping配置)的映射,这里的T代表RequestMappingInfo类型(包含了映射配置、与url匹配方式等)
			// 请求到来时会根据请求的url,由匹配方式匹配到相应的映射配置,然后根据映射配置找到相应的Method(即Handler)
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
				(MethodIntrospector.MetadataLookup<T>) method -> {
					return getMappingForMethod(method, userType);
				});
			methods.forEach((method, mapping) -> {
				// 将方法转换为AOP代理的方法
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
				// 直接委托给Mapping注册中心进行注册,注册中心为内部类MappingRegistry的一个实例
				registerHandlerMethod(handler, invocableMethod, mapping);
			});
		}
	}

	class MappingRegistry { 
		public void register(T mapping, Object handler, Method method) {
			// Kotlin语言,忽略
			if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
				...
			}
			
			this.readWriteLock.writeLock().lock();
			try {
				// 将handler与method封装为最终的Handler,对于RequestMappingHandlerMapping,最终的Handler是个HandlerMethod类型
				HandlerMethod handlerMethod = createHandlerMethod(handler, method);
				// 验证handlerMethod,主要避免重复注册
				validateMethodMapping(handlerMethod, mapping);
				// 注册RequestMappingInfo与Handler的关系,一个RequestMappingInfo可能包含多个url
				this.mappingLookup.put(mapping, handlerMethod);
				// url包含直接的url和正则的url,正则的url需要费时解析,而普通的url只需要字符串比较即可,所以单独处理直接url以提高匹配效率
				// 缓存直接url(如果是正则url则不缓存,如果是多个url,那么每一个单独缓存)
				// 直接url只需要简单的字符串比较而无需正则匹配,这样可以快速找到mapping(RequestMappingInfo)
				List<String> directUrls = getDirectUrls(mapping);
				for (String url : directUrls) {
					this.urlLookup.add(url, mapping);
				}

				// mapping名
				String name = null;
				if (getNamingStrategy() != null) {
					// 默认使用Controller的简单类名,各个单词的首字母大写 + "#" + 方法名
					// 如com.test.MyController的test()方法,那么名就是MC#test()
					name = getNamingStrategy().getName(handlerMethod, mapping);
					addMappingName(name, handlerMethod);
				}

				// 获取跨域配置,initCorsConfiguration(...)在RequestMappingHandlerMapping中实现了
				CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
				if (corsConfig != null) {
					// 注册handler与该handler对应的跨域配置
					this.corsLookup.put(handlerMethod, corsConfig);
				}

				// 注册mapping与MappingRegistration的关系
				this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
			} finally {
				this.readWriteLock.writeLock().unlock();
			}
		}
	}	
}	

public final class MethodIntrospector {
	public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
		final Map<Method, T> methodMap = new LinkedHashMap<>();
		// 初始化后会包含目标类及其实现的所有接口(包括其祖先类实现的所有接口),如果类是代理,还会包含被代理的原始类
		Set<Class<?>> handlerTypes = new LinkedHashSet<>();
		Class<?> specificHandlerType = null;

		// 如果是代理类(这里就是指Controller的代理类),那么获取原始类(即Controller本身)并注册
		if (!Proxy.isProxyClass(targetType)) {
			specificHandlerType = ClassUtils.getUserClass(targetType);
			handlerTypes.add(specificHandlerType);
		}
		// 注册目标类及其实现的所有接口(包括其祖先类实现的所有接口)
		handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));

		// 扫描目标类、原始类、及其实现的所有接口中定义的所有方法(私有方法等会被扫描)
		for (Class<?> currentHandlerType : handlerTypes) {
			// 被代理的原始类
			final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);

			// 第一个参数是目标类、第二个参数用于注册回调、第三个参数用于过滤回调(默认过滤掉桥方法与合成方法,且不包含父类中定义的方法)
			ReflectionUtils.doWithMethods(currentHandlerType, method -> {
				// 如果是特殊方法(如接口的方法等),将其转换为目标类的方法
				Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
				
				// metadataLookup是传入的一个lambda表达式,其实就是简单地回调了RequestMappingHandlerMapping.getMappingForMethod(...)
				T result = metadataLookup.inspect(specificMethod);
				if (result != null) {
					Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
					if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
						methodMap.put(specificMethod, result);
					}
				}
			}, ReflectionUtils.USER_DECLARED_METHODS);
		}

		return methodMap;
	}

	public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
		// 从此处可见,当前class定义的方法(无论是私有、保护还是公有的方法都能被注册)
		Method[] methods = getDeclaredMethods(clazz, false);
		for (Method method : methods) {
			// 过滤掉桥方法与合成方法
			if (mf != null && !mf.matches(method))  continue;
			
			// 回调进行方法注册
			mc.doWith(method);
		}
		
		// 因为传入的mf是USER_DECLARED_METHODS,所以不会扫描父类中定义的方法
		if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
			// 处理父类中定义的方法,会递归所有祖先类
			doWithMethods(clazz.getSuperclass(), mc, mf);
		} else if (clazz.isInterface()) {
			// 因为不会进入上一个分支,所以会处理接口继承的接口方法
			// 如果进入了上一个分支,说明目标类及其祖先类的方法都被处理了,那么所有接口的方法肯定也被处理了(接口的任一方法肯定被某一类实现了)
			for (Class<?> superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}
}
获取HandlerExecutionChain
// 几乎所有的HandlerMapping都继承自该类
public abstract class AbstractHandlerMapping {
	// 这是一个模板方法,子类根据自己的需求重写部分接口
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 根据请求如url,获取handler
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			// 找不到匹配的handler时的默认handler,它初始化为空,需要设置默认handler才能获得
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		
		// 如果handler是String类型的,那么handler实际上是handler注册的beanName
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}

		// 获取处理链,包括一个handler与一系列的拦截器
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		// hasCorsConfigurationSource(...)根据handler是否实现了CorsConfigurationSource接口来判断是否支持跨域
		// RequestMethodHandleMapping的handler是HandlerMethod类,不可能实现了CorsConfigurationSource接口
		// BeanNameUrlHandlerMapping的handler是Controller类,看程序员是否实现了CorsConfigurationSource接口
		// CorsUtils.isPreFlightRequest(...)根据请求信息来判断是否支持跨域
		// 请求必须包含请求头Origin和Access-Control-Request-Method,且必须是OPTIONS类型请求,那么就是跨域
		if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
			CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
			// 如果handler实现了CorsConfigurationSource接口,通过其getCorsConfiguration(...)方法获取CorsConfiguration
			// RequestMethodHandleMapping重写了该方法,先调用父类的该方法,如果无法获取CorsConfiguration,再搜索初始化时注册的
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			// 将两个CorsConfiguration属性进行合并
			config = (config != null ? config.combine(handlerConfig) : handlerConfig);
			// 在拦截器链开头添加一个拦截器,该拦截器会根据配置设置响应response的响应头
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}

		return executionChain;
	}
	
	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		// 如果传入的handler已经是HandlerExecutionChain,那么我们它已经包含了handler,无需在处理
		// 否则我们就新建一个HandlerExecutionChain并用handler进行初始化
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		// 从请求中获取相对url
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			// MappedInterceptor类型的拦截器需要匹配url才会起到拦截作用,其他类型的拦截器拦截所有请求
			// 通过配置的拦截器会被解析为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;
	}
}	
BeanNameUrlHandlerMapping
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
		// 从请求中获取相对url
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		request.setAttribute(LOOKUP_PATH, lookupPath);
		
		// 寻找handler
		Object handler = lookupHandler(lookupPath, request);
		if (handler == null) {
			Object rawHandler = null;
			// 如果路径只是一个"/",那么就优先用rootHandler来处理,rootHandler默认为null
			if ("/".equals(lookupPath)) {
				rawHandler = getRootHandler();
			}
			// 否则用默认defaultHander来处理,默认defaultHandler也为null
			if (rawHandler == null) {
				rawHandler = getDefaultHandler();
			}
			// 验证和发布参数,如果进入了该分支,那么该HandlerMapping就有默认的Handler,那么后面的HandlerMapping是无法作用的
			if (rawHandler != null) {
				if (rawHandler instanceof String) {
					String handlerName = (String) rawHandler;
					rawHandler = obtainApplicationContext().getBean(handlerName);
				}
				validateHandler(rawHandler, request);
				handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
			}
		}
		return handler;
	}

	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
		// 从handlerMap中根据key(相对url)获取Handler
		Object handler = this.handlerMap.get(urlPath);
		if (handler != null) {
			// 如果是String类型,说明得到的是beanName,通过AppicationContext来获取Bean作为handler
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			// 验证作用,实际上是个空函数
			validateHandler(handler, request);
			// 发布一些参数
			return buildPathExposingHandler(handler, urlPath, urlPath, null);
		}

		// 无法直接匹配,采取正则匹配,matchingPatterns保存匹配上的正则格式的url
		List<String> matchingPatterns = new ArrayList<>();
		for (String registeredPattern : this.handlerMap.keySet()) {
			if (getPathMatcher().match(registeredPattern, urlPath)) {
				matchingPatterns.add(registeredPattern);
			} else if (useTrailingSlashMatch()) {
				if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
					matchingPatterns.add(registeredPattern + "/");
				}
			}
		}

		// 取最小的一个作为最佳匹配的正则url
		String bestMatch = null;
		Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
		if (!matchingPatterns.isEmpty()) {
			matchingPatterns.sort(patternComparator);
			bestMatch = matchingPatterns.get(0);
		}
		
		if (bestMatch != null) {
			// 根据正则url查找到相应的handler
			handler = this.handlerMap.get(bestMatch);
			if (handler == null) {
				if (bestMatch.endsWith("/")) {
					handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
				}
				if (handler == null) {
					throw new IllegalStateException(...);
				}
			}
			
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			// 获取匹配"*"和"?"的段(段就是路径中用"/"隔开的一段段内容)
			String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);

			// 用于保存正则url中匹配的参数及其值
			Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
			for (String matchingPattern : matchingPatterns) {
				if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
					Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
					Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
					uriTemplateVariables.putAll(decodedVars);
				}
			}
			// 发布一些参数
			return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
		}

		return null;
	}

	// 用于发布一些请求相关的参数
	protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
			String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {
		// 以rawHanlder作为handler创建一个HandlerExecutionChain,以便注册默认拦截器
		HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
		// 主要将最佳匹配的路径(如/api/goods/{id})和handler发布出去(request属性方式)
		chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
		if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
			// 主要将路径中的参数值通过key-value发布到一个Map类型的request属性中
			chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
		}
		return chain;
	}
}	
RequestMappingHandlerMapping
public AbstractHandlerMethodMapping<RequestMappingInfo> extends AbstractHandlerMapping {
	// 根据请求获取Handler
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		// 从请求中获取相对url
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		request.setAttribute(LOOKUP_PATH, lookupPath);
		this.mappingRegistry.acquireReadLock();
		try {
			// 根据url找到Handler
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			// handlerMethod.createWithResolvedBean()确保用于调用Method的对象是期望的对象实例(Controller实例)
			// 如果是String类型,那么以此为beanName从ApplicationContext中获取Bean来作为期望的对象实例
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		} finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		// Match包含一个mapping,一个Handler,也就是只要匹配了,就会生成一个Match保存于此(Match的mapping只对应一个url)
		List<Match> matches = new ArrayList<>();
		// 获取能够直接匹配的mapping(非正则url的RequestMappingInfo),这是url对应的原始mapping
		// 如果该mapping初始化时包含了多个url,那么此时的mapping也包含多个url
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		// 如果找到直接匹配的mapping,那么获取
		if (directPathMatches != null) {
			// 将直接匹配的mapping进行遍历,找到对应的Handler,并且把原始mapping封装出一个新mapping(该mapping的url只有当前请求的url)
			addMatchingMappings(directPathMatches, matches, request);
		}
		// 如果无法直接匹配,那么采取正则匹配(可见正则匹配的优先级低于直接匹配的优先级)
		if (matches.isEmpty()) {
			// 将所有注册的mapping进行遍历,根据正则匹配的mapping找到Handler并与封装出新的mapping,两者组合成Match
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
			Match bestMatch = matches.get(0);
			// 如果不止一个匹配,找到最小的Match(不能有两个及以上的最小Match)
			if (matches.size() > 1) {
				Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
				matches.sort(comparator);
				bestMatch = matches.get(0);
				if (CorsUtils.isPreFlightRequest(request)) {
					return PREFLIGHT_AMBIGUOUS_MATCH;
				}
				Match secondBestMatch = matches.get(1);
				if (comparator.compare(bestMatch, secondBestMatch) == 0) {
					Method m1 = bestMatch.handlerMethod.getMethod();
					Method m2 = secondBestMatch.handlerMethod.getMethod();
					String uri = request.getRequestURI();
					throw new IllegalStateException(...);
				}
			}
			// 将handler发布出去
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
			// 将url路径中的参数及其值以map的方式保存,并以request属性的方式发布
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		} else {
			// 没有匹配handler时,其他方式获取handler,默认会返回null
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}
}	

HandlerAdapter

  该组件会根据对请求进行处理的对象来决定如何处理请求,默认使用了HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter、HandlerFunctionAdapter。可以向容器注册一个或多个HandlerAdapter实现类的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • HttpRequestHandlerAdapter
  • SimpleControllerHandlerAdapter:handler如果是Controller的子类,那么该适配器可用,可与BeanNameUrlHandlerMapping结合使用,直接调用Controller的handleRequest(…)方法来完成请求处理
  • RequestMappingHandlerAdapter:handler如果是Handler类型,那么该适配器可用,可与RequestMappingHandlerMapping结合使用
  • HandlerFunctionAdapter
  • SimpleServletHandlerAdapter
public interface HandlerAdapter {
	// 当前HandlerAdapter是否可以处理指定的handler
	boolean supports(Object handler);
	// 执行handler的处理工作,得到ModelAndView
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
	// 设置最后修改时间,一般都是直接设置为-1
	long getLastModified(HttpServletRequest request, Object handler);
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取所有HandlerAdapter实现类或名为"handlerAdapter"的Bean作为Web应用的List
	private void initHandlerAdapters(ApplicationContext context) {
		this.handlerAdapters = null;

		// this.detectAllHandlerAdapters默认为true
		if (this.detectAllHandlerAdapters) {
			// 从ApplicationContext中获取所有HandlerAdapter实现类的Bean,排序后作为Web应用的List
			Map<String, HandlerAdapter> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerAdapters = new ArrayList<>(matchingBeans.values());
				AnnotationAwareOrderComparator.sort(this.handlerAdapters);
			}
		} else {
			try {
				// 从ApplicationContext中获取名为"handlerAdapter"的Bean作为Web应用的List
				HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
				this.handlerAdapters = Collections.singletonList(ha);
			} catch (NoSuchBeanDefinitionException ex) {
				...
			}
		}
		
		if (this.handlerAdapters == null) {
			this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
		}
	}
}
初始化
SimpleControllerHandlerAdapter

  该HandlerAdapter不需要初始化。

RequestMappingHandlerAdapter

  与RequestMappingHandlerMapping一样,RequestMappingHandlerAdapter同时实现了ApplicationContextAware与InitializingBean接口,其ApplicationContextAware接口的实现方式以及成绩结构与RequestMappingHandlerMapping完全相同,这里主要介绍InitializingBean方式的初始化。

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
	public void afterPropertiesSet() {
		// 用于初始化被ControllerAdvice修饰的Bean
		initControllerAdviceCache();

		// XxxComposite表示的是一个聚合类的封装,并暴露和聚合类中单个元素相同的操作
		// 注册默认的参数处理器,用于给handler以及modelAttribute方法提供参数来源
		if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		
		// 注册默认的initBinder方法处理器,用于给initBinder方法提供参数来源
		if (this.initBinderArgumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		
		// 注册默认的返回值转换器,用于处理handler的返回值
		if (this.returnValueHandlers == null) {
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

	private void initControllerAdviceCache() {
		if (getApplicationContext() == null) {
			return;
		}

		// 获取所有被ControllerAdvice修饰的Bean实例(已经对这些Bean进行了排序)
		List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());

		List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();

		for (ControllerAdviceBean adviceBean : adviceBeans) {
			Class<?> beanType = adviceBean.getBeanType();
			if (beanType == null) {
				throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
			}
			
			// 将被@ModeAttribute修饰的方法缓存起来(即全局的ModeAttribute方法)
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
				this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
			}

			// 将被@InitBinder修饰的方法缓存起来(即全局的InitBinder方法)
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
				this.initBinderAdviceCache.put(adviceBean, binderMethods);
			}
			
			// 如果是RequestBodyAdvice或者ResponseBodyAdvice的子类,将其缓存下来
			if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
				requestResponseBodyAdviceBeans.add(adviceBean);
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {
			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}
	}
}	
HandlerMethodArgumentResolver
  • RequestParamMethodArgumentResolver
  • RequestParamMapMethodArgumentResolver
  • PathVariableMethodArgumentResolver
  • PathVariableMapMethodArgumentResolver
  • MatrixVariableMethodArgumentResolver
  • MatrixVariableMapMethodArgumentResolver
  • ServletModelAttributeMethodProcessor
  • RequestResponseBodyMethodProcessor
  • RequestPartMethodArgumentResolver
  • RequestHeaderMethodArgumentResolver
  • RequestHeaderMapMethodArgumentResolver
  • ServletCookieValueMethodArgumentResolver
  • ExpressionValueMethodArgumentResolver
  • SessionAttributeMethodArgumentResolver
  • RequestAttributeMethodArgumentResolver
  • ServletRequestMethodArgumentResolver
  • ServletResponseMethodArgumentResolver
  • HttpEntityMethodProcessor
  • RedirectAttributesMethodArgumentResolver
  • ModelMethodProcessor
  • MapMethodProcessor
  • ErrorsMethodArgumentResolver
  • SessionStatusMethodArgumentResolver
  • UriComponentsBuilderMethodArgumentResolver
  • RequestParamMethodArgumentResolver
  • ServletModelAttributeMethodProcessor
HandlerMethodReturnValueHandler
  • ModelAndViewMethodReturnValueHandler:处理返回值为ModeAndView及其子类的HandlerMethod
  • ModelMethodProcessor:处理返回值为Model及其子类的HandlerMethod
  • ViewMethodReturnValueHandler:处理返回值为View及其子类的HandlerMethod
  • ResponseBodyEmitterReturnValueHandler:
  • StreamingResponseBodyReturnValueHandler
  • HttpEntityMethodProcessor:返回值为HttpEntity的子类但不能为RequestHttpEntity及其子类的HandlerMethod
  • HttpHeadersReturnValueHandler
  • CallableMethodReturnValueHandler
  • DeferredResultMethodReturnValueHandler
  • AsyncTaskMethodReturnValueHandler
  • ModelAttributeMethodProcessor
  • RequestResponseBodyMethodProcessor:被ResponseBody修饰的Conctroller或者方法
  • ViewNameMethodReturnValueHandler
  • MapMethodProcessor
  • ModelAndViewResolverMethodReturnValueHandler
  • ModelAttributeMethodProcessor
handler执行
SimpleControllerHandlerAdapter
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}

	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		return ((Controller) handler).handleRequest(request, response);
	}
}
RequestMappingHandlerAdapter
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
	public final boolean supports(Object handler) {
		// 子类实现的supportsInternal(...)直接返回true
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

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

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
	// 直接返回true
	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		return true;
	}

	protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) {
		ModelAndView mav;
		
		// 检查请求,检查不通过会抛出异常,主要用于检查请求方法是否被支持(如GET、POST等)
		checkRequest(request);

		// 这一段就是为了执行 mav = invokeHandlerMethod(request, response, handlerMethod)这一行代码
		// 如果要让同一个用户的所有请求序列化执行,需要对同一个Session加锁(在同一个session的请求释放前,该session的访问需要排队等候)
		// 同一个用户请求的序列化访问会降低系统的吞吐量,默认是不需要加锁的
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			} else { 
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		} else {
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

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

		return mav;
	}

	protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) {
		// 封装了请求和响应
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		
		try {
			// WebDataBinderFactory包含了全局与局部的BinderMethod
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			// ModelFactory包含了BinderFactory、SessionAttributesHandler、全局与局部的ModeAttributeMethod
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			// invocableMethod包含执行的方法、BindFactory、以及参数及返回值转换方式等
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			invocableMethod.setDataBinderFactory(binderFactory);
			// 用来决定方法参数的发现名(如handler的形参应该与传入的哪个实参进行绑定)
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			// 创建一个ModeAndView容器,该容器可以保存构建ModeAndView的一些信息
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			// 将FlashMap方式重定向来的参数添加到Model容器
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			// 主要是从session中获取SessionAttribute,以及执行Model方法来获取键值对,从而初始化Model
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			// 异步请求相关设置
			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			... 更多异步请求设置 ...

			// 真正地执行handler方法,包括方法参数获取等
			invocableMethod.invokeAndHandle(webRequest, mavContainer);

			// 如果开启了异步请求,那么这里直接返回,也无需渲染视图,直接交回给Servlet容器释放线程
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			// 构建ModelAndView对象
			return getModelAndView(mavContainer, modelFactory, webRequest);
		} finally {
			// 请求处理结
			webRequest.requestCompleted();
		}
	}

	private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
		// 得到的handlerType就是Controller的类型
		Class<?> handlerType = handlerMethod.getBeanType();
		// 根据Controller类型获取其局部BinderMethod
		Set<Method> methods = this.initBinderCache.get(handlerType);
		if (methods == null) {
			// INIT_BINDER_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);
			// MethodIntrospector.selectMethods(...)用于筛选出类中符合条件的方法,这里就是筛选出被@InitBinder注解的方法
			methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
			// 缓存Controller与其局部BinderMethod的对应关系
			this.initBinderCache.put(handlerType, methods);
		}
		
		// 用于保存此次请求,全局与局部的所有BinderMethod
		List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();

		// 向本次请求注册符合条件的全局BinderMethod
		this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
			// 判断handlerType是否是配置类的子类或者被配置的注解标记,或者位于配置的包及其子包下,这些配置在@ControllerAdvice中配置
			if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
				Object bean = controllerAdviceBean.resolveBean();
				for (Method method : methodSet) {
					initBinderMethods.add(createInitBinderMethod(bean, method));
				}
			}
		});

		// 向本次请求注册局部BinderMethod
		for (Method method : methods) {
			Object bean = handlerMethod.getBean();
			initBinderMethods.add(createInitBinderMethod(bean, method));
		}
		
		// 用全局与局部的BinderMethod构建WebDataBinderFactory
		return createDataBinderFactory(initBinderMethods);
	}

	private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
		// 解析handler类(即Controller)的SessionAttributes注解,并将解析结果封装为SessionAttributesHandler对象
		// 将handler类与SessionAttributesHandler以key-value形式进行了缓存
		SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
		
		// 得到的handlerType就是Controller的类型
		Class<?> handlerType = handlerMethod.getBeanType();
		// 根据Controller类型获取其局部ModelAttributeMethod,先从缓存中取,取不到再解析然后缓存
		Set<Method> methods = this.modelAttributeCache.get(handlerType);
		if (methods == null) {
			// 筛选出handlerType类中被@ModelAttribute标记,且未被@RequestMapping标记的方法
			methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
			// 缓存Controller与其局部ModeAttributeMethod的对应关系
			this.modelAttributeCache.put(handlerType, methods);
		}
		
		// 用于保存此次请求,全局与局部的所有ModeAttributeMethod
		List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
		
		// 向本次请求注册符合条件的全局ModeAttributeMethod
		this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
			// 判断handlerType是否是配置类的子类或者被配置的注解标记,或者位于配置的包及其子包下,这些配置在@ControllerAdvice中配置
			if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
				Object bean = controllerAdviceBean.resolveBean();
				for (Method method : methodSet) {
					attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
				}
			}
		});

		// 向本次请求注册局部ModeAttributeMethod
		for (Method method : methods) {
			Object bean = handlerMethod.getBean();
			attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
		}
		
		// 用BinderFactory、SessionAttributesHandler、全局与局部的ModeAttributeMethod构建ModelFactory
		return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
	}

	private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) {
		// 将符合@SessionAttribute注解标识的Model属性放入session中
		modelFactory.updateModel(webRequest, mavContainer);

		// 如果请求已经处理完成,不需要ModelAndView就直接返回null,比如用@RequestBody标识的方法
		if (mavContainer.isRequestHandled()) {
			return null;
		}
		
		ModelMap model = mavContainer.getModel();
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		if (!mavContainer.isViewReference()) {
			mav.setView((View) mavContainer.getView());
		}

		// 如果需要重定向,将重定向参数暂存如FlashAttributes
		if (model instanceof RedirectAttributes) {
			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			if (request != null) {
				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
		}
		
		return mav;
	}
}

public final class ModelFactory {
	public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod) {
		// 从session中获取model并放入容器
		Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
		container.mergeAttributes(sessionAttributes);
		// 执行Model方法并将返回值放入Model中
		invokeModelAttributeMethods(request, container);

		// 确保用@ModelAttribute标记且能被sessionAttributes支持的参数存在与容器中
		for (String name : findSessionAttributeArguments(handlerMethod)) {
			if (!container.containsAttribute(name)) {
				Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
				if (value == null) {
					throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
				}
				container.addAttribute(name, value);
			}
		}
	}

	private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container) {
		while (!this.modelMethods.isEmpty()) {
			// 与while一起使用模拟迭代操作
			InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
			
			ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);
			if (container.containsAttribute(ann.name())) {
				if (!ann.binding()) {
					container.setBindingDisabled(ann.name());
				}
				continue;
			}

			// 执行model方法,如果返回值不为void类型,那么将返回值加入Model中
			Object returnValue = modelMethod.invokeForRequest(request, container);
			if (!modelMethod.isVoid()){
				// 根据ModelAttribute注解的value值,与返回值类型来确定key
				String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
				if (!ann.binding()) {
					container.setBindingDisabled(returnValueName);
				}
				// 将Model数据加入容器
				if (!container.containsAttribute(returnValueName)) {
					container.addAttribute(returnValueName, returnValue);
				}
			}
		}
	}
}	

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		// 先通过getMethodArgumentValues(request, mavContainer, providedArgs)获取实参列表
		// 再通过反射调用HandlerMethod方法
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		} else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

		// 还未处理完请求,未处理完的请求才会进入ModelAndView的处理
		mavContainer.setRequestHandled(false);
		
		// 依次遍历所有已注册的HandlerMethodReturnValueHandler(HandlerAdapter初始化时完成注册)
		// 直到找到支持当前返回值的Resolver并调用其handleReturnValue(...)方法,找不到抛出异常
		this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}

	// 获取方法需要的实参,在父类InvocableHandlerMethod中定义的	
	// providedArgs提供了一系列候选实参,优先从中挑选实参
	protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		// 获取方法的形参列表
		MethodParameter[] parameters = getMethodParameters();
		if (ObjectUtils.isEmpty(parameters)) {
			// 如果不须要参数,那么返回空数组
			return EMPTY_ARGS;
		}

		// args用于保存实参,和形参个数相同
		Object[] args = new Object[parameters.length];
		
		// 依次获取各个实参
		for (int i = 0; i < parameters.length; i++) {
			MethodParameter parameter = parameters[i];
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			
			// 如果提供的候选实参中有当前形参类型的子类,那么就用该候选实参作为当前形参的实参
			// 因为一般候选实参是个空数组,也就是没有候选实参,所以这里无法获取到实参
			args[i] = findProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
				continue;
			}
			
			// 依次遍历所有已注册的HandlerMethodArgumentResolver(HandlerAdapter初始化时完成注册)
			// 直到找到支持当前形参的Resolver并调用其resolveArgument(...)方法,找不到抛出异常
			if (!this.resolvers.supportsParameter(parameter)) {
				throw new IllegalStateException(...);
			}
			args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
		}
		
		return args;
	}
}	

HandlerExceptionResolver

  该组件用来解决请求处理过程中抛出的异常,默认使用了ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver。可以向容器注册一个或多个HandlerExceptionResolver实现类的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • ExceptionHandlerExceptionResolver:通过ControllerAdvice与ExceptionHandler注解来自定义异常处理方法
  • ResponseStatusExceptionResolver
  • DefaultHandlerExceptionResolver:定义了大量的针对各种Exception的处理
  • SimpleMappingExceptionResolver
public interface HandlerExceptionResolver {
	ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取所有HandlerExceptionResolver实现类或名为"handlerExceptionResolver"的Bean作为Web应用的List
	private void initHandlerExceptionResolvers(ApplicationContext context) {
		this.handlerExceptionResolvers = null;

		// this.detectAllHandlerExceptionResolvers默认为true
		if (this.detectAllHandlerExceptionResolvers) {
			// 从ApplicationContext中获取所有HandlerExceptionResolver实现类的Bean,排序后作为Web应用的List
			Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
					.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
				AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
			}
		} else {
			try {
				// 从ApplicationContext中获取名为"handlerExceptionResolver"的Bean作为Web应用的List
				HandlerExceptionResolver her = context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
				this.handlerExceptionResolvers = Collections.singletonList(her);
			} catch (NoSuchBeanDefinitionException ex) {
				...
			}
		}

		if (this.handlerExceptionResolvers == null) {
			this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
		}
	}	
}
ExceptionHandlerExceptionResolver
初始化

  ExceptionHandlerExceptionResolver同时实现了ApplicationContextAware与InitializingBean接口,在setApplicationContext(…)只是完成了applicationContext的注入功能,具体的初始化过程发生在afterPropertiesSet()中。

public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
		implements ApplicationContextAware, InitializingBean {
	public void afterPropertiesSet() {
		// Do this first, it may add ResponseBodyAdvice beans
		initExceptionHandlerAdviceCache();

		// 为异常处理函数提供参数
		if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}

		// 为异常处理函数返回值提供处理
		if (this.returnValueHandlers == null) {
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

	private void initExceptionHandlerAdviceCache() {
		if (getApplicationContext() == null) {
			return;
		}

		// 获取所有被@ControllerAdvice注解的Bean
		List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
		for (ControllerAdviceBean adviceBean : adviceBeans) {
			Class<?> beanType = adviceBean.getBeanType();
			if (beanType == null) {
				throw new IllegalStateException(...);
			}
			
			// 筛选出所有被@ExceptionHandler注解的方法,并解析方法能够处理的异常,以能处理的异常为key,当前方法为value进行注册
			// 这样就能在发生全局异常时,根据异常类型,找到相应的处理方法
			ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);
			if (resolver.hasExceptionMappings()) {
				this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
			}
			if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
				this.responseBodyAdvice.add(adviceBean);
			}
		}
	}

	protected List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		resolvers.add(new ModelMethodProcessor());
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		return resolvers;
	}

	protected List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
		List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
		handlers.add(new ModelAndViewMethodReturnValueHandler());
		handlers.add(new ModelMethodProcessor());
		handlers.add(new ViewMethodReturnValueHandler());
		handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));
		handlers.add(new ModelAttributeMethodProcessor(false));
		handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));
		handlers.add(new ViewNameMethodReturnValueHandler());
		handlers.add(new MapMethodProcessor());
		if (getCustomReturnValueHandlers() != null) {
			handlers.addAll(getCustomReturnValueHandlers());
		}
		handlers.add(new ModelAttributeMethodProcessor(true));

		return handlers;
	}
}

public class ExceptionHandlerMethodResolver {
	public ExceptionHandlerMethodResolver(Class<?> handlerType) {
		// 筛选出所有被@ExceptionHandler注解的方法
		for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) {
			// 注册当前method能够处理的异常类型
			for (Class<? extends Throwable> exceptionType : detectExceptionMappings(method)) {
				addExceptionMapping(exceptionType, method);
			}
		}
	}

	private List<Class<? extends Throwable>> detectExceptionMappings(Method method) {
		List<Class<? extends Throwable>> result = new ArrayList<>();
		// 将method上的ExceptionHandler注解的值(一个元素类型为Throwable的数组)放入result中
		detectAnnotationExceptionMappings(method, result);
		if (result.isEmpty()) {
			// 如果ExceptionHandler注解没有指定处理哪一类型的异常,那么形参有什么类型的异常就处理什么类型的异常
			for (Class<?> paramType : method.getParameterTypes()) {
				if (Throwable.class.isAssignableFrom(paramType)) {
					result.add((Class<? extends Throwable>) paramType);
				}
			}
		}
		
		// 如果既没有用ExceptionHandler注解指定处理的异常类型,也没有通过形参来指定异常类型,那么程序有误,抛出异常
		if (result.isEmpty()) {
			throw new IllegalStateException(...);
		}
		
		return result;
	}
}	
异常处理
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
		implements ApplicationContextAware, InitializingBean {

	public Method resolveMethod(Exception exception) {
		return resolveMethodByThrowable(exception);
	}

	public Method resolveMethodByThrowable(Throwable exception) {
		Method method = resolveMethodByExceptionType(exception.getClass());
		// 如果找不到当前异常处理的方法,那么就根据引起异常的异常来找处理的方法,依次递归下去
		if (method == null) {
			Throwable cause = exception.getCause();
			if (cause != null) {
				method = resolveMethodByExceptionType(cause.getClass());
			}
		}
		return method;
	}

	public Method resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) {
		// 这里又使用了缓存
		Method method = this.exceptionLookupCache.get(exceptionType);
		if (method == null) {
			// 获取异常对应的处理函数
			method = getMappedMethod(exceptionType);
			this.exceptionLookupCache.put(exceptionType, method);
		}
		return method;
	}

	private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
		// 筛选出能够处理当前异常的所有key(即已注册的异常中,当前异常父类的异常)
		List<Class<? extends Throwable>> matches = new ArrayList<>();
		for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
			if (mappedException.isAssignableFrom(exceptionType)) {
				matches.add(mappedException);
			}
		}
		
		// 如果找到了能处理当前异常的处理方法,先对其排序,然后取第一个(也就是优先级最高的)
		// 根据当前异常到比较异常的继承深度排序,深度越小越靠前,如A->B->C,很明显B到A的深度比C到A的深度小
		if (!matches.isEmpty()) {
			matches.sort(new ExceptionDepthComparator(exceptionType));
			return this.mappedMethods.get(matches.get(0));
		} else {
			return null;
		}
	}
}	

RequestToViewNameTranslator

  该组件用来从请求中获取默认的viewName(如果ModeAndView已经有了view,那么该组件将不会起作用),默认使用DefaultRequestToViewNameTranslator。可以向容器注册一个名为"viewNameTranslator"的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • DefaultRequestToViewNameTranslator
public interface RequestToViewNameTranslator {
	String getViewName(HttpServletRequest request) throws Exception;
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取名为"viewNameTranslator"的Bean作为Web应用的RequestToViewNameTranslator
	private void initRequestToViewNameTranslator(ApplicationContext context) {
		try {
			this.viewNameTranslator = context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);
		} catch (NoSuchBeanDefinitionException ex) {
			this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);
		}
	}
}

ViewResolver

  该组件用于将viewName转换为View对象,默认使用InternalResourceViewResolver。可以向容器注册一个或多个ViewResolver实现类的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • InternalResourceViewResolver:主要用来将JSP文件解析为视图
  • BeanNameViewResolver
  • ContentNegotiatingViewResolver
  • FreeMarkerViewResolver
  • ResourceBundleViewResolver
  • UrlBasedViewResolver
  • XmlViewResolver
public interface ViewResolver {
	// view的render(...)方法进行响应的渲染,返回不同类型的View,其渲染方式也不一样
	View resolveViewName(String viewName, Locale locale) throws Exception;
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取所有ViewResolver实现类或名为"viewResolver"的Bean作为Web应用的List
	// 默认只有org.springframework.web.servlet.view.InternalResourceViewResolver
	private void initViewResolvers(ApplicationContext context) {
		this.viewResolvers = null;

		// this.detectAllViewResolvers默认为true
		if (this.detectAllViewResolvers) {
			// 从ApplicationContext中获取所有ViewResolver实现类的Bean,排序后作为Web应用的List
			Map<String, ViewResolver> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.viewResolvers = new ArrayList<>(matchingBeans.values());
				AnnotationAwareOrderComparator.sort(this.viewResolvers);
			}
		} else {
			try {
				// 从ApplicationContext中获取名为"viewResolver"的Bean作为Web应用的List
				ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
				this.viewResolvers = Collections.singletonList(vr);
			} catch (NoSuchBeanDefinitionException ex) {
				...
			}
		}

		if (this.viewResolvers == null) {
			this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
		}
	}
}

FlashMapManager

  该组件用于解决重定向过程中的参数传递问题,默认使用SessionFlashMapManager。可以向容器注册一个名为"flashMapManager"的bean来覆盖默认组件。

  spring-mvc中提供的实现类有:

  • SessionFlashMapManager:以session为载体,在重定向前将参数存入session中,重定向请求到来时从session获取参数并从将参数从session中删除。
public interface FlashMapManager {
	FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
	void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}

public class DispatcherServlet extends FrameworkServlet {
	// 从ApplicationContext中获取名为"flashMapManager"的Bean作为Web应用的FlashMapManager
	private void initFlashMapManager(ApplicationContext context) {
		try {
			this.flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
		} catch (NoSuchBeanDefinitionException ex) {
			this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class);
		}
	}
}

访问请求

DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet -> GenericServlet -> Servlet

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
	// 当请求到达Servlet容器时,Servlet容器会根据请求的url找到匹配的且已在Servlet容器注册过的Servlet并调用其service(...)方法
	// 对于SpringMVC,所有的url都被映射到DispatherServlet,而DispatherServlet起作用的service(...)在父类FrameworkServlet中实现
	// 实际上所有请求都是直接调用了processRequest(...)方法(doOptions(...)除外)
	protected void service(HttpServletRequest request, HttpServletResponse response) {		
		HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
		// 因为Servlet中并没有定义PATCH方法(PATCH是对PUT的扩展,并不是HTTP协议规定的方法),所以无法交给HttpServlet处理
		if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
			processRequest(request, response);
		} else {
			// 调用HttpServlet的service(...)方法,这部分属于JavaEE内容,实际上就是根据请求方法调用相应的doXxx(...)方法,如doGet(...)
			// 而doXxx(...)方法在FrameworkServlet中进行了实现,几乎都是直接调用processRequest(...)方法(doOptions(...)除外)
			super.service(request, response);
		}
	}

	// 请求处理
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response) {
		long startTime = System.currentTimeMillis();
		Throwable failureCause = null;

		// LocaleContextHolder包含一个ThreadLocal变量,用于为每个线程保存一个LocaleContext
		// 通过LocaleContextHolder的静态方法getLocaleContext()可以很方便的获取到LocaleContext(LocaleContextHolder几乎都是静态方法,这样在任何地方都可以直接调用)
		// LocaleContext只有一个方法就是getLocale(),通过它可以获取到Locale对象
		// 如果在此代码之前设置了当前线程的LocaleContext(如Servlet编程的Filter中),那么在后面的代码该LocaleContext是无效的
		// 创建并设置新的LocaleContext前,获取老的LocaleContext是为了后面代码的还原操作
		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();		
		// 根据请求,由this.localeResolver来完成LocaleContext的创建
		LocaleContext localeContext = buildLocaleContext(request);

		// 与LocaleContextHolder原理类似,只是ServletRequestAttributes提供了其他功能
		// 通过ServletRequestAttributes可以获取HttpServletRequest、HttpSession以及在相应对象中保存的attribute
		// SpringWeb的request与session作用范围就是基于该对象的
		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
		
		// 将新创建的LocaleContext与ServletRequestAttributes设置到当前线程(后面代码会在请求处理完成时设置回原值)		
		// 如果在请求处理的过程中新创建了线程(如业务逻辑service中),那么在新线程中无法通过该方法获取到Locale对象
		initContextHolders(request, localeContext, requestAttributes);

		// WebAsyncManager类似于Servlet编程中的AsyncContext,用于异步编程(类似Servlet3引入的异步编程),与@Async注解没有任何关系
		// WebAsyncUtils会直接new一个WebAsyncManager并缓存在当前ServletRequest的attribute中
		// 这样同一个请求范围内,通过WebAsyncUtils.getAsyncManager(...)都将获得同一个WebAsyncManager对象
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		// 通过asyncManager执行的异步线程,在执行自定义代码前后会进行额外的回调处理,这里注册了RequestBindingInterceptor类型的回调处理
		// RequestBindingInterceptor用于在执行自定义代码前后分别执行initContextHolders(...)与resetContextHolders(...)方法
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

		try {
			// 该方法完成最主要的逻辑,在子类DispatherServlet中进行了定义
			doService(request, response);
		} catch (Throwable ex) {
			failureCause = ex;
			throw ex;
		} finally {
			// 将当前线程的LocaleContext与RequestAttributes还原,这样在之后的操作(如Servlet编程的Filter中)获取的依然是原值
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				// 请求结束额外处理,如销毁request-scope的Bean,更新Session等
				requestAttributes.requestCompleted();
			}
			// 发布一个ServletRequestHandledEvent事件,继承ApplicationListener的监听器可监听此事件
			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}

	// 创建LocaleContext
	protected LocaleContext buildLocaleContext(final HttpServletRequest request) {
		// this.localeResolver在初始化过程中完成了注入
		LocaleResolver lr = this.localeResolver;
		if (lr instanceof LocaleContextResolver) {
			return ((LocaleContextResolver) lr).resolveLocaleContext(request);
		} else {
			// LocaleContext是个函数式接口,所以这里用Lambda表达式来表示一个匿名内部类
			return () -> (lr != null ? lr.resolveLocale(request) : request.getLocale());
		}
	}

	// 处理跨域请求
	protected void doOptions(HttpServletRequest request, HttpServletResponse response) {
		if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {
			processRequest(request, response);
			if (response.containsHeader("Allow")) {
				return;
			}
		}
		
		super.doOptions(request, new HttpServletResponseWrapper(response) {
			@Override
			public void setHeader(String name, String value) {
				if ("Allow".equals(name)) {
					value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();
				}
				super.setHeader(name, value);
			}
		});
	}
}

public class DispatcherServlet extends FrameworkServlet {
	protected void doService(HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> attributesSnapshot = null;
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// 把一些常用的对象发布到请求域,以便在其他地方可以方便获取这些对象
		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());

		if (this.flashMapManager != null) {
			// 获取通过FlashMapManager重定向而来的参数,并将其保存在request中,同时将这些参数从FlashMapManager中清空(因为这些参数只在重定向中使用一次)
			FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
			if (inputFlashMap != null) {
				request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
			}
			// 创建一个想要重定向时的空的参数持有者,供后面存放数据
			request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
			// 将flashMapManager发布出去,让别的地方能够方便地获取到flashMapManager
			request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
		}

		try {
			doDispatch(request, response);
		} finally {
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				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 {
				// 如果是文件上传请求,就将请求封装为MultipartHttpServletRequest返回
				processedRequest = checkMultipart(request);
				// 是否是文件上传请求
				multipartRequestParsed = (processedRequest != request);

				// HandlerExecutionChain包含一个handler,以及一个HandlerInterceptor数组
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					// 在找不到处理方法的时候,直接向response里面写入404状态
					noHandlerFound(processedRequest, response);
					return;
				}

				// 获取可以处理handler的适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// 拦截器前处理,顺序调用HandlerInterceptor数组中每一个元素的preHandle(...)方法
				// 如果某一个HandlerInterceptor的preHandle(...)返回false,那么不会继续往后调用并直接返回false
				// 在上一步如果返回的是false,那么还会倒序调用所有HandlerInterceptor的afterCompletion(...)方法
				// 如果拦截器链的调用最终返回false,就不会执行下面的控制器、视图等的处理了
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 通过适配器来调用处理方法,并将结果封装为ModelAndView
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				// 如果当前线程开启了异步,那么暂时不处理视图与后置处理,直接返回以便快速释放线程
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
			
				// 如果ModeAndView中没有view,那么通过viewNameTranslator从请求获取默认view
				applyDefaultViewName(processedRequest, mv);

				// 拦截器后处理,倒序调用HandlerInterceptor数组中每一个元素的postHandle(...)方法
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			} catch (Throwable ex) {
				dispatchException = ex;
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		} catch (Throwableex) {
			// 执行所有拦截器的afterCompletion(...)方法
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		} finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			} else {
				// 如果不是异步且是文件上传请求,且已经处理,那么需要做清除工作
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

	// 如果是文件上传请求,就将请求封装为MultipartHttpServletRequest返回
	protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
		if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
			if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
				if (request.getDispatcherType().equals(DispatcherType.REQUEST)) {
					logger.trace(...);
				}
			} else if (hasMultipartException(request)) {
				logger.debug(...);
			} else {
				return this.multipartResolver.resolveMultipart(request);
			}
		}
		
		return request;
	}

	// 遍历注册的所有HandlerMapping,直到找到HandlerExecutionChain
	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;
	}

	// 遍历注册的所有HandlerAdapter,直到某个HandlerAdapter的supports(...)方法返回true,表示HandlerAdapter能够处理handler
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		
		throw new ServletException(...);
	}

	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) {
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			} else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				// 依次调用已注册的HandlerExceptionResolver,直到某个Resolver的返回不为null为止,如果最终返回null,说明所有注册的Resolver都无法处理该异常
				mv = processHandlerException(request, response, handler, exception);
				// 如果上一步返回的ModelAndView为null,表示异常未得到解决,ModelAndView也不是异常得到的ModelAndView
				errorView = (mv != null);
			}
		}

		if (mv != null && !mv.wasCleared()) {
			// 通过view来渲染响应
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			return;
		}

		if (mappedHandler != null) {
			// 执行所有拦截器的afterCompletion(...)方法
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) {
		Locale locale = (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		// 根据viewName得到view
		View view;
		String viewName = mv.getViewName();
		if (viewName != null) {
			// 遍历所有的ViewResolver,直到能将viewName转换为View为止
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException(...;
			}
		} else {
			view = mv.getView();
			if (view == null) {
				throw new ServletException(...);
			}
		}

		if (mv.getStatus() != null) {
			response.setStatus(mv.getStatus().value());
		}

		// 通过view来渲染响应
		view.render(mv.getModelInternal(), request, response);
	}
}

你可能感兴趣的:(#,Spring源码分析)