0%

SpringMVC

一、总流程

  1. 用户发送请求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求,选择合适的HandlerMapping(处理器映射器)。
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),找到的Handler和拦截器一起生成HandlerExecutionChain,返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter(处理器适配器)。
  5. HandlerAdapter适配调用具体的Handler(Controller,也叫后端控制器)。
  6. Handler执行完具体逻辑,返回ModelAndView。
  7. HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体View,这个view不是完整的,仅仅是一个页面(视图)名字,且没有后缀名。
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。

二、加载配置文件

使用SpringMVC时,一般通过web.xml文件配置Tomcat容器applicationContext.xml文件配置spring IOC容器springmvc.xml文件配置MVC容器

2.1、web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

<!--配置上下文监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--加载applicationContext配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>

<!--配置springmvc前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载springMVC配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--配置启动初始化(在启动tomcat时候就创建单例的servlet)-->
<!--数字越小越先加载-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>

2.2、springmvc.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!--1.注解扫描-->
<!--SpringMVC中之扫描controller包下的注解-->
<context:component-scan base-package="com.yrl.controller"/>
<!--2.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--3.注解驱动-->
<mvc:annotation-driven/>
</beans>

<mvc:annotation-driven/>标签相当于同时配置RequestMappingHandlerMapping和RequestMappingHandlerAdapter

2.3、applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!--1.开启注解扫描-->
<!--这里只扫描service包.因为Spring与SpringMVC都要开启注解扫描,不要重复扫描包-->
<context:component-scan base-package="com.yrl.service"/>

</beans>

三、Tomcat

基于Tomcat-8.5进行分析

3.1、加载web.xml

TomcatStandardContext组件在初始化启动时,会加载web.xml配置文件,将web.xml中配置的servlet、listener、fiter进行创建

如上面配置的web.xml将创建ContextLoaderListenerDispatcherServlet

3.2、StandardContext

Tomcat组件的初始化创建会产生相应的生命周期事件。

以下代码做过简化,详情请点击查看Tomcat篇。

1
2
3
4
5
6
7
8
public class StandardContext extends ContainerBase implements Context{
protected synchronized void startInternal() throws LifecycleException {
//1、启动对应监听器
listenerStart();
//2、载并初始化web应用程序通过loadOnStartup指定的Servlet
loadOnStartup(findChildren())
}
}

3.2.1、listenerStart

启动对应监听器,初始化IOC容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class StandardContext extends ContainerBase implements Context{
public boolean listenerStart() {
// 1.1. 获取生命周期类的事件处理器
Object instances[] = getApplicationLifecycleListeners();
// 1.2. 封装ServletContextEvent
ServletContextEvent event = new ServletContextEvent(getServletContext());
// 1.3. 依次调用Tomcat容器中ServletContextListener的监听器处理当前ServletContextEvent事件
for (Object instance : instances) {
if (!(instance instanceof ServletContextListener)) {
continue;
}
ServletContextListener listener = (ServletContextListener) instance;
// 调用监听器的contextInitialized()方法
listener.contextInitialized(event);
}
}
return ok;
}
}

3.2.2、loadOnStartup

加载并初始化Servlet

1
2
3
4
5
6
7
8
public class StandardContext extends ContainerBase implements Context{
public boolean loadOnStartup(Container children[]) {
//...
//2。1、加载并初始化Servlet
wrapper.load();
//...
}
}

3.3、总结

3.3.1、ContextLoaderListener

StandardContext组件初始化启动,会调用ontextLoaderListenercontextInitialized(event)方法发送ServletContextEvent事件,此处会创建刷新IOC容器。

3.3.2、DispatcherServlet

加载web.xml中指定<load-on-startup>属性的Servlet,即我们配置的DispatcherServlet,初始化MVC相关组件。

四、初始化

基于spring-webmvc-5.2.15进行分析

4.1、IOC容器

4.1.1、ContextLoaderListener

ContextLoaderListener接收ServletContextEvent事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
/**
* 初始化 root web application context.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
// 将上下文存储在本地实例变量中,以确保它在ServletContext关闭时可用。
if (this.context == null) {
//创建应用上下文,即Spring IOC容器
this.context = createWebApplicationContext(servletContext);
}
//...
//将创建的root web应用上下文,即IOC容器放入servletContext的属性中(MVC容器创建时会取出,建立父子容器关系)
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
}
}

4.1.2、创建IOC容器

当没有使用<context-param>contextClass属性指定root WebApplicationContext的实现类时,默认实例化XmlWebApplicationContext作为IOC容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* 实例化这个加载器的根 WebApplicationContext,可以是默认的上下文类,也可以是指定的自定义上下文类。
* 这个实现期望自定义上下文来实现ConfigurableWebApplicationContext接口。可以在子类中重写。
* 此外,在刷新上下文之前调用customizeContext,允许子类对上下文执行自定义修改。
*/
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
//1、确定使用的上下文类对象
Class<?> contextClass = determineContextClass(sc);
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
}
//2、使用类的无参数构造函数实例化类-XmlWebApplicationContext。
return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
}

/**
* 有使用contextClass属性指定root WebApplicationContext的实现类的按照自定义类对象返回
* 没有指定实现类,则从ContextLoader.properties配置文件中获取默认上下文XmlWebApplicationContext的类对象
*/
protected Class<?> determineContextClass(ServletContext servletContext) {
//1.1、contextClass属性指定root WebApplicationContext的实现类
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class [" + contextClassName + "]", ex);
}
}
else {
//1.2、没有指定实现类,则从ContextLoader.properties配置文件中获取默认上下文XmlWebApplicationContext的类对象
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName + "]", ex);
}
}
}

ContextLoader.properties配置文件
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

4.1.3、配置并刷新IOC容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
/**
* 初始化 root web application context.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
// 将上下文存储在本地实例变量中,以确保它在ServletContext关闭时可用。
if (this.context == null) {
//1、创建应用上下文,即IOC容器
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
// 上下文还没有刷新->提供诸如设置父上下文、设置应用程序上下文id等服务
if (cwac.getParent() == null) {
// 上下文实例注入时没有显式的父级->确定根web应用程序上下文的父级(如果有的话)。
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
//2、配置并刷新应用上下文
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
//3、将当前创建的应用上下文放入ServletContext的属性中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

//...

return this.context;
}


protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {

wac.setServletContext(sc);
//...
// 1. web.xml文件中<context-param>配置的`contextConfigLocation`属性,做为IOC容器启动的初始化文件
// 主要包括IOC容器中Service、Manager、Dao以及其他非Controller层的Bean包扫描信息及注解驱动
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
//...
// 2. 可扩展点,可以用于在IOC容器刷新前前做一些自定义的操作
customizeContext(sc, wac);
// 3. 调用refresh()方法进行IOC容器的初始化
wac.refresh();
}
}

4.1.4、refresh

调用AbstractApplicationContext的refresh方法对应用上下文(IOC容器进)进行初始化,具体方法这不做介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 1、设置容器的启动时间
* 2、设置活跃状态为true
* 3、设置关闭状态为false
* 4、获取Environment对象,并加载当前系统的属性值到Environment对象中
* 5、准备监听器和事件的集合对象,默认为空的集合
*/
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
// 创建容器对象:DefaultListableBeanFactory
// 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
// beanFactory的准备工作,对各种属性进行填充
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// 调用各种beanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
// 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
// 为上下文初始化message源,即不同语言的消息体,国际化处理,在springmvc的时候通过国际化的代码重点讲
initMessageSource();

// Initialize event multicaster for this context.
// 初始化事件监听多路广播器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 留给子类来初始化其他的bean(SpringBoot会基于此方法创建web Server)
onRefresh();

// Check for listener beans and register them.
// 在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的单实例(非懒加载的)
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
// 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单例bean
destroyBeans();

// Reset 'active' flag.
// 重置active标志
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

4.2、DispatcherServlet

4.2.1、初始化-Tomcat侧

由Tomcat源码分析可知,StandardContext组件加载web.xml,由于DispatcherServlet配置<load-on-startup>所以被StandardContext提前实例化并初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class StandardWrapper extends ContainerBase implements ServletConfig, Wrapper, NotificationEmitter {

@Override
public synchronized void load() throws ServletException {
//实例化Servlet
instance = loadServlet();

//初始化Servlet
if (!instanceInitialized) {
initServlet(instance);
}
//...
}

private synchronized void initServlet(Servlet servlet)
throws ServletException {
servlet.init(facade);
}
}

public abstract class GenericServlet implements Servlet, ServletConfig,java.io.Serializable {

@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}

//调用子类实现
public void init() throws ServletException {
// NOOP by default
}

}

以上是对Tomcat对Servlet的实例化和初始化

4.2.2、初始化-MVC侧

子类实现初始化

1
2
3
4
5
6
7
8
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {

@Override
public final void init() throws ServletException {
//子类实现初始化
initServletBean();
}
}

创建MVC容器

创建MVC容器,将ContextLoaderListener初始化创建的springIOC容器作为MVC容器的父容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
@Override
protected final void initServletBean() throws ServletException {
//1、初始化创建web应用上下文
this.webApplicationContext = initWebApplicationContext();
//空方法,等待子类实现
initFrameworkServlet();
}
protected WebApplicationContext initWebApplicationContext() {
//1.1、从servletContext的属性中取出之前创建的root web应用上下文,即Spring IOC容器
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());

if (wac == null) {
//1.2、创建MVC应用上下文容器,并将之前创建的Spring IOC容器作为其父容器
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
//1.3、调用子类初始化组件策略
onRefresh(wac);
}
}

protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
return createWebApplicationContext((ApplicationContext) parent);
}

protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
//1.2.1、创建MVC应用上下文容器
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
//1.2.2、配置环境参数
wac.setEnvironment(getEnvironment());
//1.2.3、将之前创建的Spring IOC容器作为其父容器
wac.setParent(parent);
//1.2.4、设置contextConfigLocation属性指定的springmvc.xml文件
wac.setConfigLocation(getContextConfigLocation());
//1.2.5、配置并刷新容器
configureAndRefreshWebApplicationContext(wac);

return wac;
}
}

初始化九大组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class DispatcherServlet extends FrameworkServlet {
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}

//初始化九大组件
protected void initStrategies(ApplicationContext context) {
//初始化 MultipartResolver:主要用来处理文件上传.如果定义过当前类型的bean对象,
//那么直接获取,如果没有的话,可以为null
initMultipartResolver(context);
//初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver),
//基于session的配置(SessionLocaleResolver),基于cookie的配置(CookieLocaleResolver)
initLocaleResolver(context);
//初始化 ThemeResolver:主要用来设置主题Theme
initThemeResolver(context);
//初始化 HandlerMapping:映射器,用来将对应的request跟controller进行对应
initHandlerMappings(context);
//初始化 HandlerAdapter:处理适配器,主要包含Http请求处理器适配器,
//简单控制器处理器适配器,注解方法处理器适配器
initHandlerAdapters(context);
//初始化 HandlerExceptionResolver:基于HandlerExceptionResolver接口的异常处理
initHandlerExceptionResolvers(context);
//初始化 RequestToViewNameTranslator:当controller处理器方法没有返回一个View对象或逻辑视图名称,
//并且在该方法中没有直接往response的输出流里面写数据的时候,spring将会采用约定好的方式提供一个逻辑视图名称
initRequestToViewNameTranslator(context);
//初始化 ViewResolver: 将ModelAndView选择合适的视图进行渲染的处理器
initViewResolvers(context);
//初始化 FlashMapManager: 提供请求存储属性,可供其他请求使用
initFlashMapManager(context);
}
}

4.3、总结

Tomcat在初始化Web应用时会通过事件监听器进行IOC容器的初始化,接着Tomcat在初始化Servlet时,会通过Servletinit()方法进行mvc容器的初始化,并设置MVC容器与IOC容器的父子关系

4.4、DispatcherServlet.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 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

4.5、初始化HandlerMapping

初始化HandlerMapping,如果BeanFactory中没有,则从DispatcherServlet.properties文件中获取默认实现,BeanNameUrlHandlerMappingRequestMappingHandlerMappingRouterFunctionMapping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;

if (this.detectAllHandlerMappings) {
//1、如果xml有配置,会被容器管理,此处能够找到
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
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.
}
}
//2、没有其他自定义配置,使用默认实现
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}


protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
//2.1、从DispatcherServlet.properties文件中获取默认HandlerMapping实现
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<T>(classNames.length);
for (String className : classNames) {
try {
//2,2、通过上下文的BeanFactory创建默认实现,BeanNameUrlHandlerMapping、DefaultAnnotationHandlerMapping
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Error loading DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]: problem with class file or dependent class", err);
}
}
return strategies;
}
else {
return new LinkedList<T>();
}
}

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

4.6、初始化HandlerAdapters

与初始化HandlerMapping类似。

初始化HandlerAdapter,如果BeanFactory中没有,则从DispatcherServlet.properties文件中获取默认实现,HttpRequestHandlerAdapterSimpleControllerHandlerAdapterRequestMappingHandlerAdapterHandlerFunctionAdapter

五、HandlerMapping

5.1、初始化拦截器

Spring初始化HandlerMapping子类时,触发setApplicationContext方法,子类初始化拦截器(当通过getHandler方法时会将找到的handler与拦截器一起生成HandlerExecutionChain返回)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public abstract class ApplicationObjectSupport implements ApplicationContextAware {
@Override
public final void setApplicationContext(@Nullable ApplicationContext context) throws BeansException {
if (context == null && !isContextRequired()) {
//...
}
else if (this.applicationContext == null) {
// Initialize with passed-in context.
//...
this.applicationContext = context;
this.messageSourceAccessor = new MessageSourceAccessor(context);
//初始化,调用子类AbstractHandlerMapping实现
initApplicationContext(context);
}
else {
//...
}
}

protected void initApplicationContext(ApplicationContext context) throws BeansException {
//子类AbstractHandlerMapping实现
initApplicationContext();
}

}

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware {
//初始化拦截器
@Override
protected void initApplicationContext() throws BeansException {
//spring提供钩子函数,子类可以实现该方法来为集合设置拦截器
extendInterceptors(this.interceptors);
//从spring容器中获取所有MappedInterceptor,添加到adaptedInterceptors中
detectMappedInterceptors(this.adaptedInterceptors);
//将interceptors初始化成 HandlerInterceptor类型,添加到adaptedInterceptors中
initInterceptors();
}
}

5.2、BeanNameUrlHandlerMapping

初始化父类initApplicationContext,调用detectHandlers寻找匹配的handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {

@Override
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
detectHandlers();
}

protected void detectHandlers() throws BeansException {
ApplicationContext applicationContext = obtainApplicationContext();
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
applicationContext.getBeanNamesForType(Object.class));

// Take any bean name that we can determine URLs for.
for (String beanName : beanNames) {
//调用子类实现,查找bean的名称和别名以“/”开头的url
String[] urls = determineUrlsForHandler(beanName);
if (!ObjectUtils.isEmpty(urls)) {
// URL paths found: Let's consider it a handler.
registerHandler(urls, beanName);
}
}

if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {
logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
}
}
}

5.2.1、determineUrlsForHandler

BeanNameUrlHandlerMapping实现determineUrlsForHandler方法,寻找bean的名称和别名以“/”开头的url。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {

/**
* Checks name and aliases of the given bean for URLs, starting with "/".
*/
@Override
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);
}

}

5.2.2、registerHandler

注册handler,建立url与handler的关系

1
2
3
4
5
6
7
8
9
10
11
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {

private final Map<String, Object> handlerMap = new LinkedHashMap<>();

protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
Assert.notNull(urlPaths, "URL path array must not be null");
for (String urlPath : urlPaths) {
registerHandler(urlPath, beanName);
}
}
}

5.3、RequestMappingHandlerMapping

1
2
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> 
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean

初始化

afterPropertiesSet

springIOC容器初始化RequestMappingHandlerMapping时会调用InitializingBean的afterPropertiesSet方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements EmbeddedValueResolverAware {
@Override
public void afterPropertiesSet() {
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setPatternParser(getPathPatternParser());
this.config.setContentTypeResolver(getContentTypeResolver());

super.afterPropertiesSet();
}
}

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Override
public void afterPropertiesSet() {
//初始化handler
initHandlerMethods();

// Total includes detected mappings + explicit registrations via registerMapping..
int total = this.getHandlerMethods().size();

if ((logger.isTraceEnabled() && total == 0) || (logger.isDebugEnabled() && total > 0) ) {
logger.debug(total + " mappings in " + formatMappingName());
}
}
}

initHandlerMethods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {

/**
* 扫描ApplicationContext中的bean,检测并注册处理程序方法。
*/
protected void initHandlerMethods() {
//获取容器管理的bean对象名称
String[] beanNames = obtainApplicationContext().getBeanNamesForType(Object.class);

for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
//判断当前bean是否可以作为handler,包含Controller注解或者RequestMapping注解则匹配
if (beanType != null && isHandler(beanType)) {
//寻找匹配的handler方法
detectHandlerMethods(beanName);
}
}
}
handlerMethodsInitialized(getHandlerMethods());
}

}
isHandler

判断当前bean是否可以作为handler,判定条件:被@Controller或者 @RequestMapping修饰

1
2
3
4
5
6
7
8
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements EmbeddedValueResolverAware {

@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
}
detectHandlerMethods

寻找合适的HandlerMethod(被@RequestMapping修饰的方法)进行注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
protected void detectHandlerMethods(final Object handler) {
//获取handler的class对象
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());

if (handlerType != null) {
//返回给定类的用户定义类:通常简单地返回给定类,但如果是cglib生成的子类,则返回原始类。
final Class<?> userType = ClassUtils.getUserClass(handlerType);
// 遍历当前bean的所有方法,筛选出合适的 handler 方法 以及 注解信息
// getMappingForMethod方法寻找@RequestMapping 注解修饰的方法,selectMethods方法会过滤null值
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> getMappingForMethod(method, userType));
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
//经上面过滤,此时的methods都是被 @RequestMapping 注解修饰的方法
methods.forEach((method, mapping) -> {
//这里是针对 cglib 代理特殊处理
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
//注册 HandlerMethod
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
}
getMappingForMethod

使用方法和类级别的@RequestMapping注解创建RequestMappingInfo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements EmbeddedValueResolverAware {

@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
//转换成 RequestMappingInfo ,如果方法没有被 @RequestMapping 注解修饰,则会返回null
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
// 解析出来 bean 上 @RequestMapping 注解的各种信息
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
// 合并类和方法的 @RequestMapping 注解信息
info = typeInfo.combine(info);
}
//// 获取前缀,拼接前缀
for (Map.Entry<String, Predicate<Class<?>>> entry : this.pathPrefixes.entrySet()) {
if (entry.getValue().test(handlerType)) {
String prefix = entry.getKey();
if (this.embeddedValueResolver != null) {
prefix = this.embeddedValueResolver.resolveStringValue(prefix);
}
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
break;
}
}
}
return info;
}

@Nullable
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
}
registerHandlerMethod

注册一个处理程序方法及其唯一的映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements EmbeddedValueResolverAware {
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
//调用AbstractHandlerMethodMapping的registerHandlerMethod方法
super.registerHandlerMethod(handler, method, mapping);
updateConsumesCondition(mapping, method);
}

private void updateConsumesCondition(RequestMappingInfo info, Method method) {
ConsumesRequestCondition condition = info.getConsumesCondition();
if (!condition.isEmpty()) {
for (Parameter parameter : method.getParameters()) {
MergedAnnotation<RequestBody> annot = MergedAnnotations.from(parameter).get(RequestBody.class);
if (annot.isPresent()) {
condition.setBodyRequired(annot.getBoolean("required"));
break;
}
}
}
}
}

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
/**
* 注册一个处理程序方法及其唯一的映射。
* 在启动时为每个检测到的处理程序方法调用。
* @param handler 处理程序或处理程序实例的bean名称
* @param method 注册方法
* @param mapping 与处理程序方法关联的映射条件
* 如果在同一个映射下已经注册了另一个方法,@throws IllegalStateException
*/
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}

class MappingRegistry {
// RequestMappingInfo 和 MappingRegistration 的映射关系
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
// key:RequestMappingInfo, value:HandlerMethod
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
// HandlerMethod 和 CorsConfiguration 的映射关系
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();

private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();


public void register(T mapping, Object handler, Method method) {
//写锁
this.readWriteLock.writeLock().lock();
try {
// 将 handler 和 method 封装成一个HandlerMethod
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
// 校验实例的合法性,即唯一性
validateMethodMapping(handlerMethod, mapping);
//保存映射关系,key:RequestMappingInfo,value:HandlerMethod
this.mappingLookup.put(mapping, handlerMethod);

//@CrossOrigin跨域注解请求的初始化配置
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}

this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
}
}

六、HandlerAdapter

6.1、HttpRequestHandlerAdapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}

@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}

6.2、SimpleControllerHandlerAdapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}

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

return ((Controller) handler).handleRequest(request, response);
}

@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}

6.3、RequestMappingHandlerAdapter

AbstractHandlerMethodAdapter,HandlerAdapter实现的抽象基类,支持HandlerMethod类型的处理程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
public RequestMappingHandlerAdapter() {
//消息转换器,用于http请求和相应的消息转换
this.messageConverters = new ArrayList<>(4);
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
try {
this.messageConverters.add(new SourceHttpMessageConverter<>());
}
catch (Error err) {
// Ignore when no TransformerFactory implementation is available
}
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}

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

@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//使用指定的handler方法处理请求
return handleInternal(request, response, (HandlerMethod) handler);
}

@Override
public final long getLastModified(HttpServletRequest request, Object handler) {
return getLastModifiedInternal(request, (HandlerMethod) handler);
}
}

handleInternal

使用指定的handler方法处理请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {

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

ModelAndView mav;
//查请求类型和session支持
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) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}

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

return mav;
}
}

invokeHandlerMethod

调用RequestMapping的handler处理方法,返回一个ModelAndView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//基于request和response创建ServletWebRequest对象
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
//查找当前处理类中所有包含@InitBinder注解修饰的方法;查找@ControllerAdive注解修饰的类中包含的@InitBinder方法
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
//查找当前处理类中所有包含@ModelAttribute注解修饰的方法;查找@ControllerAdive注解修饰的类中包含的@ModelAttribute方法
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

//创建ServletInvocableHandlerMethod对象,并设置其相关属性,实际的请求处理就是通过此对象来完成的,参数绑定、处理请求以及返回值处理都在里边完成
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
//设置参数处理器
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
//设置返回值处理器
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
//设置binderFactory
invocableMethod.setDataBinderFactory(binderFactory);
//设置参数名称发现器
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

//创建ModelAndViewContainer对象,用于保存model和View对象
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异步请求管理器对象,设置属性值,判断是否开始异步请求
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);
}

//调用 handler方法
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}

// 1、调用ModelFactory的updateModel方法更新model,包括设置SessionAttribute和给Model设置BinderResult
// 2、根据mavContainer创建了ModelAndView
// 3、如果mavContainer里的model是RedirectAttributes类型,则将其设置到FlashMap
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
//表示请求已经完成,执行所有的请求销毁回调,并更新请求处理过程中访问过的会话属性
webRequest.requestCompleted();
}
}
invokeAndHandle

调用该方法并通过配置的HandlerMethodReturnValueHandlers处理返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

//处理调用请求
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;
}

mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
//处理返回值
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
}
invokeForRequest

匹配支持的参数解析器,解析获取参数并调真实逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class InvocableHandlerMethod extends HandlerMethod {

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

}
  • getMethodArgumentValues-匹配支持的参数解析器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    public class InvocableHandlerMethod extends HandlerMethod {

    protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
    Object... providedArgs) throws Exception {

    MethodParameter[] parameters = getMethodParameters();
    if (ObjectUtils.isEmpty(parameters)) {
    return EMPTY_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支持给定的方法参数。
    //内部会将找到的HandlerMethodArgumentResolver放入argumentResolverCache缓存,后面调用可以直接获取
    if (!this.resolvers.supportsParameter(parameter)) {
    throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
    }
    try {
    //遍历已注册的HandlerMethodArgumentResolvers并调用解析参数
    //先从argumentResolverCache缓存中获取
    args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
    }
    catch (Exception ex) {
    // Leave stack trace for later, exception may actually be resolved and handled...
    if (logger.isDebugEnabled()) {
    String exMsg = ex.getMessage();
    if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
    logger.debug(formatArgumentError(parameter, exMsg));
    }
    }
    throw ex;
    }
    }
    return args;
    }
    }
  • doInvoke

    通过Method.invoke反射调用真实逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class InvocableHandlerMethod extends HandlerMethod {
    @Nullable
    protected Object doInvoke(Object... args) throws Exception {
    ReflectionUtils.makeAccessible(getBridgedMethod());
    try {
    //如果bean方法是桥接方法,则此方法返回桥接的(用户定义的)方法。否则,它返回与getMethod()相同的方法。
    //Method.invoke反射调用真实逻辑
    return getBridgedMethod().invoke(getBean(), args);
    }
    catch (IllegalArgumentException ex) {
    //...
    }
    catch (InvocationTargetException ex) {
    //...
    }
    }
    }
handleReturnValue

匹配支持的返回值处理器,处理返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
//查询支持的返回值处理器
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
//调用返回值处理器处理返回值
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}

@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}

}
  • RequestResponseBodyMethodProcessor

    • 解析带有@RequestBody注解的方法参数,并通过HttpMessageConverter读写请求或响应的主体来处理带有@ResponseBody注解的方法的返回值。

    • 如果@RequestBody方法参数带有@javax.validation.Valid注解,也会验证它。如果验证失败,则会抛出MethodArgumentNotValidException异常,如果配置了DefaultHandlerExceptionResolver,则会返回HTTP 400响应状态码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
    //判断是否支持处理返回值类型
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
    return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
    returnType.hasMethodAnnotation(ResponseBody.class));
    }

    //处理返回值
    @Override
    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
    ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
    throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
    //设置requestHandled为true,表示请求已经在handler中处理,之后getModelAndView方法不会处理
    mavContainer.setRequestHandled(true);
    ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
    ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

    // Try even with null return value. ResponseBodyAdvice could get involved.
    writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
    }
    }
  • ModelAndViewMethodReturnValueHandler

    • 处理ModelAndView类型的返回值,将视图和模型信息复制到ModelAndViewContainer。

    • 如果返回值为null,则将ModelAndViewContainer.setRequestHandled(布尔值)标志设置为true,表示直接处理了请求。

    • ModelAndView的返回类型有一个设定的目的。因此,这个处理程序应该配置在支持任何带@ModelAttribute或@ResponseBody注解的返回值类型的处理程序之前,以确保它们不会接管。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
    return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
    }
    @Override
    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
    ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

    if (returnValue == null) {
    mavContainer.setRequestHandled(true);
    return;
    }

    ModelAndView mav = (ModelAndView) returnValue;
    if (mav.isReference()) {
    String viewName = mav.getViewName();
    mavContainer.setViewName(viewName);
    if (viewName != null && isRedirectViewName(viewName)) {
    mavContainer.setRedirectModelScenario(true);
    }
    }
    else {
    View view = mav.getView();
    mavContainer.setView(view);
    if (view instanceof SmartView && ((SmartView) view).isRedirectView()) {
    mavContainer.setRedirectModelScenario(true);
    }
    }
    mavContainer.setStatus(mav.getStatus());
    mavContainer.addAllAttributes(mav.getModel());
    }
    }
getModelAndView

调用ModelFactory的updateModel方法更新model,包括设置SessionAttribute和给Model设置BinderResult

根据mavContainer创建了ModelAndView

如果mavContainer里的model是RedirectAttributes类型,则将其设置到FlashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
@Nullable
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
//更新model,包括设置SessionAttribute和给Model设置BinderResult
modelFactory.updateModel(webRequest, mavContainer);
//请求是否在处理程序中被完全处理
if (mavContainer.isRequestHandled()) {
return null;
}
ModelMap model = mavContainer.getModel();
//根据mavContainer创建了ModelAndView
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
//如果mavContainer里的model是RedirectAttributes类型,则将其设置到FlashMap
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;
}
}

七、访问

7.1、Tomcat的Connector组件

  • 初始化
    • 创建CoyoteAdapter,用于将Tomcat请求响应对象适配为Servlet请求响应对象
    • NioEndpoint,基于NIO创建服务端端口监听
  • 启动
    • 创建Acceptor接收器、Poller轮询器
    • Acceptor接收客户连接
    • Poller处理读写事件
    • CoyoteAdapter将Tomcat请求响应对象适配为Servlet请求响应对象;
    • 将请求、响应传到后面的组件处理,Container使用Pipeline-Valve管道来处理请求
      • 寻找host
      • 记录总结指定请求和响应的消息
      • 输出HTML错误页面
      • 匹配合适的Context处理
      • 匹配合适的Wrapper处理
      • 分配Servlet、构建过滤器链
      • 调用servlet子类类service方法

7.2、HttpServlet

HttpServlet调用service方法实现,最终调用子类实现的doXXX方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public abstract class HttpServlet extends GenericServlet {
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {

HttpServletRequest request;
HttpServletResponse response;

try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
//调用子类实现
service(request, response);
}

protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

String method = req.getMethod();

if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}

} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);

} else if (method.equals(METHOD_POST)) {
doPost(req, resp);

} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);

} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);

} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);

} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);

} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//

String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);

resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
}

7.3、FrameworkServlet

doxxx方法最终都调用了processRequest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {

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

@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
/**
* 处理此请求,不管结果如何,发布一个事件.
* 实际的事件处理由抽象的doService模板方法执行
*/
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

long startTime = System.currentTimeMillis();
Throwable failureCause = null;

//返回与当前线程关联的LocaleContext(如果有的话),请求结束后重置回去
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//为给定的请求构建LocaleContext,将请求的主语言环境公开为当前语言环境
LocaleContext localeContext = buildLocaleContext(request);

//返回当前绑定到线程的RequestAttributes,请求结束后重置回去
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
//为给定的请求构建ServletRequestAttributes(可能还包含对响应的引用),将预先绑定的属性(及其类型)考虑在内
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

//获取当前请求的WebAsyncManager,如果没有找到,则创建它并将其与请求关联
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
//注册拦截器到callableInterceptors
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

//初始化LocaleContextHolder、RequestContextHolder
initContextHolders(request, localeContext, requestAttributes);

try {
//子类实现此方法来完成请求处理工作,接收GET、POST、PUT和DELETE的集中回调
//调用DispatcherServlet#doService
doService(request, response);
}
catch (Throwable ex) {
//...
}

finally {
//重置上下文
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}

//...
//请求结束,发布一个请求处理事件-ServletRequestHandledEvent
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}


private void publishRequestHandledEvent(
HttpServletRequest request, HttpServletResponse response, long startTime, Throwable failureCause) {

if (this.publishEvents) {
// Whether or not we succeeded, publish an event.
long processingTime = System.currentTimeMillis() - startTime;
int statusCode = (responseGetStatusAvailable ? response.getStatus() : -1);
//发布事件
this.webApplicationContext.publishEvent(
new ServletRequestHandledEvent(this,
request.getRequestURI(), request.getRemoteAddr(),
request.getMethod(), getServletConfig().getServletName(),
WebUtils.getSessionId(request), getUsernameForRequest(request),
processingTime, failureCause, statusCode));
}
}

}

7.4、DispatcherServlet

doService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class DispatcherServlet extends FrameworkServlet {
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}

// 在包含的情况下保留请求属性的快照,以便能够在包含之后恢复原始属性。
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<String, Object>();
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));
}
}
}

// 设置sevlet的WebApplicationContext
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
//设置国际化解析器
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
//设置主题解析器
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
//如果有的话,返回这个servlet的ThemeSource;否则返回null
//默认是返回WebApplicationContext作为ThemeSource,前提是它实现了ThemeSource接口
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

//FlashMap用于解决重定向后新请求拿不到原请求数据问题
//找到前一个请求保存的与当前请求匹配的FlashMap,将其从底层存储中删除,并删除其他过期的FlashMap实例。
//与saveOutputFlashMap不同,saveOutputFlashMap只在有flash属性需要保存时调用,即在重定向之前。
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());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

try {
//将请求分派给合适的处理器处理
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// 在包含的情况下,恢复原始属性快照。
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
}

doDispatch

  • 处理文件上传
  • 通过handlerMappings,确定一个Handler,与拦截器一起封装成HandlerExecutionChain
  • 寻找合适的HandlerAdapter
  • 调用拦截器的前处理方法
  • 实际调用,处理器适配器执行
  • 调用拦截器的后处理方法
  • 处理程序选择和调用的结果,要么是一个ModelAndView,要么是一个需要解析到ModelAndView的异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
ModelAndView mv = null;
Exception dispatchException = null;

try {
//1、处理文件上传
//将请求转换为multipart请求,并使multipart解析器可用。
//如果没有设置multipart解析器,只需使用现有的请求。
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

//2、通过handlerMappings,确定一个handler来处理当前请求
//将handler和HandlerInterceptor封装为HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
//未找到处理器,返回404
noHandlerFound(processedRequest, response);
return;
}

// 3、在handlerAdapters中寻找能到处理此handler的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;
}
}
//4、调用拦截器的前处理方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// 5、实际调用,处理器适配器执行(参考-六、HandlerAdapter)
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

// 6、当前请求的处理程序是否选择异步处理请求
//true:表示正在进行并发处理,响应将保持打开状态;
//false:并发处理要么没有开始,要么可能已经完成,请求被分派去进一步处理并发结果
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//没有视图名称的话,将url设置为默认视图名
applyDefaultViewName(processedRequest, mv);
//7、调用拦截器的后处理方法
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);
}
//8、处理程序选择和调用的结果,要么是一个ModelAndView,要么是一个需要解析到ModelAndView的异常。
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
//再次判断当前请求的处理程序是否选择异步处理请求
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
//指定AsyncHandlerInterceptor的afterConcurrentHandlingStarted方法
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// 清理由multipart请求使用的任何资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

handle

处理器适配器调用执行handler,具体参考-六、HandlerAdapter

processDispatchResult

处理返回结果,包括处理异常、渲染页面、触发Interceptor的afterCompletion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class DispatcherServlet extends FrameworkServlet {

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {

boolean errorView = false;

if (exception != null) {
//是否ModelAndViewDefiningException类型,是则获取错误内容的ModelAndView
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
//基于处理器异常解析器处理错误,返回错误内容的ModelAndView
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}

// Did the handler return a view to render?
//handler是否返回要渲染的视图
if (mv != null && !mv.wasCleared()) {
//渲染给定的模型和视图
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}
//是否异步处理
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}

if (mappedHandler != null) {
// Exception (if any) is already handled..
//触发Interceptor的afterCompletion
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
}
render

渲染给定的模型和视图,这是处理请求的最后一个阶段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class DispatcherServlet extends FrameworkServlet {

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;
String viewName = mv.getViewName();
if (viewName != null) {
//将给定的视图名解析为一个待渲染的视图对象
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对象
// No need to lookup: the ModelAndView object contains the actual View object.
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() + "'");
}
}

// Delegate to the View object for rendering.
if (logger.isTraceEnabled()) {
logger.trace("Rendering view [" + view + "] ");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "]", ex);
}
throw ex;
}
}
}
resolveViewName

默认情况下springmvc使用InternalResourceViewResolver作为其视图解析器

调用视图解析器生成视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class DispatcherServlet extends FrameworkServlet {

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

if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}
}

从缓存获取视图,不存在则创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver {
@Override
@Nullable
public View resolveViewName(String viewName, Locale locale) throws Exception {
//缓存限制是否大于0,即是否有开启缓存
if (!isCache()) {
return createView(viewName, locale);
}
else {
//viewName + '_' + locale作为缓存key
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) {
// 调用子类实现创建视图
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);
}
}
}

创建视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {

@Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
//如果这个视图解析器不处理这个视图名称,则返回null
if (!canHandle(viewName, locale)) {
return null;
}

// 检查是否有 "redirect:" 特殊前缀.
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
//截取要重定向的url
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
//使用给定的URL创建一个新的RedirectView
RedirectView view = new RedirectView(redirectUrl,
isRedirectContextRelative(), isRedirectHttp10Compatible());
//返回配置的应用程序hosts用于重定向
String[] hosts = getRedirectHosts();
if (hosts != null) {
view.setHosts(hosts);
}
//调用上下文容器的initializeBean去初始化view对象,REDIRECT_URL_PREFIX作为beanName
return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
}

// 检查是否有 "forward:" 特殊前缀.
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
//截取要转发的url
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
//使用给定的URL创建一个新的InternalResourceView
InternalResourceView view = new InternalResourceView(forwardUrl);
//调用上下文容器的initializeBean去初始化view对象,FORWARD_URL_PREFIX作为beanName
return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
}

// 不属于转发、重定向的,调用父类的createView方法
return super.createView(viewName, locale);
}
}

委托buildView创建指定视图类的新实例。

应用以下Spring生命周期方法(由通用Spring bean工厂支持):

  • ApplicationContextAware的setApplicationContext

  • InitializingBean的afterPropertiesSet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver {
@Nullable
protected View createView(String viewName, Locale locale) throws Exception {
return loadView(viewName, locale);
}
}

public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
//创建视图对象
AbstractUrlBasedView view = buildView(viewName);
//调用上下文容器的initializeBean方法对view进行初始化
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}

}

buildView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class InternalResourceViewResolver extends UrlBasedViewResolver {
@Override
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
//创建视图对象
InternalResourceView view = (InternalResourceView) super.buildView(viewName);
if (this.alwaysInclude != null) {
view.setAlwaysInclude(this.alwaysInclude);
}
view.setPreventDispatchLoop(true);
return view;
}
}
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
//InternalResourceViewResolver默认viewClass为InternalResourceView.class
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;
}
}

applyLifecycleMethods

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
protected View applyLifecycleMethods(String viewName, AbstractUrlBasedView view) {
ApplicationContext context = getApplicationContext();
if (context != null) {
//执行Bean初始化
Object initialized = context.getAutowireCapableBeanFactory().initializeBean(view, viewName);
if (initialized instanceof View) {
return (View) initialized;
}
}
return view;
}
}