diff --git a/README.md b/README.md index c6e9673..f220758 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ 有被“读过哪些知名的开源项目源码?”这种问题所困扰过吗?加入我们,一起通读互联网公司主流框架及中间件源码,成为强大的“源码猎人”,目前开放的有 Spring 系列框架、Mybatis 框架、Netty 框架,及 Redis、Tomcat 中间件等,让我们一起开拓新的领地,揭开这些源码的神秘面纱。本项目主要用于记录框架及中间件源码的阅读经验、个人理解及解析,希望能够使阅读源码变成一件更简单有趣,且有价值的事情,抽空更新中...(如果本项目对您有帮助,请watch、star、fork 素质三连一波,鼓励一下作者,谢谢) -## Spring系列 -### IoC容器 +## Spring 系列 +### IoC 容器 - [BeanDefinition 的资源定位过程](/docs/Spring/IoC/1、BeanDefinition的资源定位过程.md) - [将 bean 解析封装成 BeanDefinition](/docs/Spring/IoC/2、将bean解析封装成BeanDefinition.md) - [将 BeanDefinition 注册进 IoC 容器](/docs/Spring/IoC/3、将BeanDefinition注册进IoC容器.md) @@ -30,13 +30,13 @@ ### SpringJDBC - 努力编写中... -### Spring事务 +### Spring 事务 - [Spring 与事务处理](/docs/Spring/SpringTransaction/Spring与事务处理.md) - [Spring 声明式事务处理](/docs/Spring/SpringTransaction/Spring声明式事务处理.md) - [Spring 事务处理的设计与实现](/docs/Spring/SpringTransaction/Spring事务处理的设计与实现.md) - [Spring 事务管理器的设计与实现](/docs/Spring/SpringTransaction/Spring事务管理器的设计与实现.md) -### Spring源码故事(瞎编版) +### Spring 源码故事(瞎编版) - [面筋哥 IoC 容器的一天(上)](/docs/Spring/Spring源码故事(瞎编版)/面筋哥IoC容器的一天(上).md) ### Spring 类解析 @@ -105,7 +105,7 @@ - [基于WebSocket协议的Netty开发](docs/Netty/Netty多协议开发/基于WebSocket协议的Netty开发.md) - [基于自定义协议的Netty开发](docs/Netty/Netty多协议开发/基于自定义协议的Netty开发.md) -### 基于Netty开发服务端及客户端 +### 基于 Netty 开发服务端及客户端 - [基于Netty的服务端开发](docs/Netty/基于Netty开发服务端及客户端/基于Netty的服务端开发.md) - [基于Netty的客户端开发](docs/Netty/基于Netty开发服务端及客户端/基于Netty的客户端开发.md) diff --git a/docs/JDK/ConcurrentHashMap.md b/docs/JDK/ConcurrentHashMap.md new file mode 100644 index 0000000..753e53e --- /dev/null +++ b/docs/JDK/ConcurrentHashMap.md @@ -0,0 +1 @@ +努力编写中... \ No newline at end of file diff --git a/docs/JDK/HashMap.md b/docs/JDK/HashMap.md new file mode 100644 index 0000000..753e53e --- /dev/null +++ b/docs/JDK/HashMap.md @@ -0,0 +1 @@ +努力编写中... \ No newline at end of file diff --git a/docs/JDK/String.md b/docs/JDK/String.md new file mode 100644 index 0000000..753e53e --- /dev/null +++ b/docs/JDK/String.md @@ -0,0 +1 @@ +努力编写中... \ No newline at end of file diff --git a/docs/Spring/IoC/4、依赖注入(DI).md b/docs/Spring/IoC/4、依赖注入(DI).md index e501f8f..9a1be6a 100644 --- a/docs/Spring/IoC/4、依赖注入(DI).md +++ b/docs/Spring/IoC/4、依赖注入(DI).md @@ -1390,7 +1390,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra ## lazy-init 属性触发的依赖注入 最后看一下 lazy-init 触发的预实例化和依赖注入,发生在 IoC 容器完成对 BeanDefinition 的定位、载入、解析和注册之后。通过牺牲 IoC 容器初始化的性能,来有效提升应用第一次获取该 bean 的效率。 - lazy-init 实现的入口方法在我们前面解读过的 AbstractApplicationContext 的 refresh() 中,它是 IoC 容器正式启动的标志。 +lazy-init 实现的入口方法在我们前面解读过的 AbstractApplicationContext 的 refresh() 中,它是 IoC 容器正式启动的标志。 ```java public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean { @@ -1443,7 +1443,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader /** * !!!!!!!!!!!!!!!!!!!!! - * 对配置了 lazy-init属性为true的bean 进行预实例化 + * 对配置了 lazy-init属性 为 false 的 bean 进行预实例化 * !!!!!!!!!!!!!!!!!!!!! */ finishBeanFactoryInitialization(beanFactory); @@ -1465,7 +1465,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader } /** - * 对配置了 lazy-init属性为true的bean 进行预实例化 + * 对配置了 lazy-init属性 为 false 的 bean 进行预实例化 */ protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 这是 Spring3 以后新加的代码,为容器指定一个转换服务 (ConversionService) @@ -1492,7 +1492,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader // 缓存容器中所有注册的 BeanDefinition 元数据,以防被修改 beanFactory.freezeConfiguration(); - // 对配置了 lazy-init属性 的 单例bean 进行预实例化处理 + // 对配置了 lazy-init属性 为 false 的 单例bean 进行预实例化处理 beanFactory.preInstantiateSingletons(); } } diff --git a/docs/Spring/SpringMVC/SpringMVC的设计与实现.md b/docs/Spring/SpringMVC/SpringMVC的设计与实现.md index cf27340..9d55081 100644 --- a/docs/Spring/SpringMVC/SpringMVC的设计与实现.md +++ b/docs/Spring/SpringMVC/SpringMVC的设计与实现.md @@ -25,137 +25,137 @@ DispatcherServlet 的工作大致可以分为两个部分:一个是初始化 ```java public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { - public final void init() throws ServletException { - if (logger.isDebugEnabled()) { - logger.debug("Initializing servlet '" + getServletName() + "'"); - } - - // 获取 Servlet 的初始化参数,对 bean属性 进行配置 - try { - PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); - BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); - ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); - bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); - initBeanWrapper(bw); - bw.setPropertyValues(pvs, true); - } - catch (BeansException ex) { - logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); - throw ex; - } - - // 这个方法会调用子类的实现,进行具体的初始化 - initServletBean(); - - if (logger.isDebugEnabled()) { - logger.debug("Servlet '" + getServletName() + "' configured successfully"); - } - } + public final void init() throws ServletException { + if (logger.isDebugEnabled()) { + logger.debug("Initializing servlet '" + getServletName() + "'"); + } + + // 获取 Servlet 的初始化参数,对 bean属性 进行配置 + try { + PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); + BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); + ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); + bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); + initBeanWrapper(bw); + bw.setPropertyValues(pvs, true); + } + catch (BeansException ex) { + logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); + throw ex; + } + + // 这个方法会调用子类的实现,进行具体的初始化 + initServletBean(); + + if (logger.isDebugEnabled()) { + logger.debug("Servlet '" + getServletName() + "' configured successfully"); + } + } } public abstract class FrameworkServlet extends HttpServletBean { - /** 此 servlet 的 WebApplicationContext */ - private WebApplicationContext webApplicationContext; - - /** 我们是否应该将当前 Servlet 的上下文 webApplicationContext 设为 ServletContext 的属性 */ - private boolean publishContext = true; - - public FrameworkServlet() { - } - - public FrameworkServlet(WebApplicationContext webApplicationContext) { - this.webApplicationContext = webApplicationContext; - } - - /** - * 覆盖了父类 HttpServletBean 的空实现 - */ - @Override - protected final void initServletBean() throws ServletException { - getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); - if (this.logger.isInfoEnabled()) { - this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started"); - } - long startTime = System.currentTimeMillis(); - - try { - // 初始化上下文 - this.webApplicationContext = initWebApplicationContext(); - initFrameworkServlet(); - } - catch (ServletException ex) { - this.logger.error("Context initialization failed", ex); - throw ex; - } - catch (RuntimeException ex) { - this.logger.error("Context initialization failed", ex); - throw ex; - } - - if (this.logger.isInfoEnabled()) { - long elapsedTime = System.currentTimeMillis() - startTime; - this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + - elapsedTime + " ms"); - } - } - - /** - * 为这个 Servlet 初始化一个公共的 WebApplicationContext实例 - */ - protected WebApplicationContext initWebApplicationContext() { - // 获取根上下文作为当前 MVC上下文 的双亲上下文,这个根上下文保存在 ServletContext 中 - WebApplicationContext rootContext = - WebApplicationContextUtils.getWebApplicationContext(getServletContext()); - WebApplicationContext wac = null; - - if (this.webApplicationContext != null) { - // 可以在本对象被构造时注入一个 webApplicationContext实例 - wac = this.webApplicationContext; - if (wac instanceof ConfigurableWebApplicationContext) { - ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; - if (!cwac.isActive()) { - // 上下文尚未刷新 -> 提供诸如设置父上下文、设置应用程序上下文id等服务 - if (cwac.getParent() == null) { - // 上下文实例在没有显式父实例的情况下被注入 -> - // 将根上下文(如果有的话;可以为空)设置为父上下文 - cwac.setParent(rootContext); - } - configureAndRefreshWebApplicationContext(cwac); - } - } - } - if (wac == null) { - // 在本对象被构造时没有注入上下文实例 -> - // 查看是否已在 servlet上下文 中注册了上下文实例。 - // 如果存在一个,则假定父上下文(如果有的话)已经被设置, - // 并且用户已经执行了任何初始化,例如设置上下文ID - wac = findWebApplicationContext(); - } - if (wac == null) { - // 没有为此 servlet 定义上下文实例 -> 创建本地实例 - wac = createWebApplicationContext(rootContext); - } - - if (!this.refreshEventReceived) { - // 上下文不是支持刷新的 ConfigurableApplicationContext,或者 - // 在构造时注入的上下文已经完成刷新 -> 在此处手动触发 onRefresh()方法 - onRefresh(wac); - } - - if (this.publishContext) { - // 把当前建立的上下文保存到 ServletContext 中,使用的属性名是和 当前servlet名 相关的 - String attrName = getServletContextAttributeName(); - getServletContext().setAttribute(attrName, wac); - if (this.logger.isDebugEnabled()) { - this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + - "' as ServletContext attribute with name [" + attrName + "]"); - } - } - - return wac; - } + /** 此 servlet 的 WebApplicationContext */ + private WebApplicationContext webApplicationContext; + + /** 我们是否应该将当前 Servlet 的上下文 webApplicationContext 设为 ServletContext 的属性 */ + private boolean publishContext = true; + + public FrameworkServlet() { + } + + public FrameworkServlet(WebApplicationContext webApplicationContext) { + this.webApplicationContext = webApplicationContext; + } + + /** + * 覆盖了父类 HttpServletBean 的空实现 + */ + @Override + protected final void initServletBean() throws ServletException { + getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); + if (this.logger.isInfoEnabled()) { + this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started"); + } + long startTime = System.currentTimeMillis(); + + try { + // 初始化上下文 + this.webApplicationContext = initWebApplicationContext(); + initFrameworkServlet(); + } + catch (ServletException ex) { + this.logger.error("Context initialization failed", ex); + throw ex; + } + catch (RuntimeException ex) { + this.logger.error("Context initialization failed", ex); + throw ex; + } + + if (this.logger.isInfoEnabled()) { + long elapsedTime = System.currentTimeMillis() - startTime; + this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + + elapsedTime + " ms"); + } + } + + /** + * 为这个 Servlet 初始化一个公共的 WebApplicationContext实例 + */ + protected WebApplicationContext initWebApplicationContext() { + // 获取根上下文作为当前 MVC上下文 的双亲上下文,这个根上下文保存在 ServletContext 中 + WebApplicationContext rootContext = + WebApplicationContextUtils.getWebApplicationContext(getServletContext()); + WebApplicationContext wac = null; + + if (this.webApplicationContext != null) { + // 可以在本对象被构造时注入一个 webApplicationContext实例 + wac = this.webApplicationContext; + if (wac instanceof ConfigurableWebApplicationContext) { + ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; + if (!cwac.isActive()) { + // 上下文尚未刷新 -> 提供诸如设置父上下文、设置应用程序上下文id等服务 + if (cwac.getParent() == null) { + // 上下文实例在没有显式父实例的情况下被注入 -> + // 将根上下文(如果有的话;可以为空)设置为父上下文 + cwac.setParent(rootContext); + } + configureAndRefreshWebApplicationContext(cwac); + } + } + } + if (wac == null) { + // 在本对象被构造时没有注入上下文实例 -> + // 查看是否已在 servlet上下文 中注册了上下文实例。 + // 如果存在一个,则假定父上下文(如果有的话)已经被设置, + // 并且用户已经执行了任何初始化,例如设置上下文ID + wac = findWebApplicationContext(); + } + if (wac == null) { + // 没有为此 servlet 定义上下文实例 -> 创建本地实例 + wac = createWebApplicationContext(rootContext); + } + + if (!this.refreshEventReceived) { + // 上下文不是支持刷新的 ConfigurableApplicationContext,或者 + // 在构造时注入的上下文已经完成刷新 -> 在此处手动触发 onRefresh()方法 + onRefresh(wac); + } + + if (this.publishContext) { + // 把当前建立的上下文保存到 ServletContext 中,使用的属性名是和 当前servlet名 相关的 + String attrName = getServletContextAttributeName(); + getServletContext().setAttribute(attrName, wac); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + + "' as ServletContext attribute with name [" + attrName + "]"); + } + } + + return wac; + } } ``` 至此,这个 MVC 的上下文就建立起来了,具体取得根上下文的过程在 WebApplicationContextUtils 中实现。这个根上下文是 ContextLoader 设置到 ServletContext 中去的,使用的属性是 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,ContextLoader 还对这个 IoC容器 的 Bean 配置文件进行了设置,默认的位置是在 /WEB-INF/applicationContext.xml文件 中。由于这个根上下文是 DispatcherServlet 建立的上下文的 双亲上下文,所以根上下文中管理的 Bean 也可以被 DispatcherServlet 的上下文使用。通过 getBean() 向 IoC容器 获取 Bean 时,容器会先到它的 双亲IoC容器 中获取。 @@ -165,129 +165,129 @@ public abstract class FrameworkServlet extends HttpServletBean { * 不能对其进行实例化 */ public abstract class WebApplicationContextUtils { - /** - * 使用了 WebApplicationContext 的 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性,获取 - * ServletContext 中的根上下文,这个属性代表的根上下文在 ContextLoaderListener 初始化的 - * 过程中被建立 - */ - public static WebApplicationContext getWebApplicationContext(ServletContext sc) { - return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); - } - - /** - * 查找此 web应用程序 的自定义 WebApplicationContext - */ - public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { - Assert.notNull(sc, "ServletContext must not be null"); - Object attr = sc.getAttribute(attrName); - if (attr == null) { - return null; - } - if (attr instanceof RuntimeException) { - throw (RuntimeException) attr; - } - if (attr instanceof Error) { - throw (Error) attr; - } - if (attr instanceof Exception) { - throw new IllegalStateException((Exception) attr); - } - if (!(attr instanceof WebApplicationContext)) { - throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr); - } - return (WebApplicationContext) attr; - } + /** + * 使用了 WebApplicationContext 的 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性,获取 + * ServletContext 中的根上下文,这个属性代表的根上下文在 ContextLoaderListener 初始化的 + * 过程中被建立 + */ + public static WebApplicationContext getWebApplicationContext(ServletContext sc) { + return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); + } + + /** + * 查找此 web应用程序 的自定义 WebApplicationContext + */ + public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { + Assert.notNull(sc, "ServletContext must not be null"); + Object attr = sc.getAttribute(attrName); + if (attr == null) { + return null; + } + if (attr instanceof RuntimeException) { + throw (RuntimeException) attr; + } + if (attr instanceof Error) { + throw (Error) attr; + } + if (attr instanceof Exception) { + throw new IllegalStateException((Exception) attr); + } + if (!(attr instanceof WebApplicationContext)) { + throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr); + } + return (WebApplicationContext) attr; + } ) ``` 回到 FrameworkServlet 的实现中来看一下,DispatcherServlet 的上下文是怎样建立的,这个建立过程与前面建立根上下文的过程非常类似。建立 DispatcherServlet 的上下文,需要把根上下文作为参数传递给它。然后使用反射技术来实例化上下文对象,并为它设置参数。根据默认的配置,这个上下文对象也是 XmlWebApplicationContext对象,这个类型是在 DEFAULT_CONTEXT_CLASS参数 中设置好并允许 BeanUtilis 使用的。在实例化结束后,需要为这个上下文对象设置好一些基本的配置,这些配置包括它的双亲上下文、Bean配置文件 的位置等。完成这些配置以后,最后通过调用 IoC容器 的 refresh()方法 来完成 IoC容器 的最终初始化,这和前面我们对 IoC容器实现原理 的分析中所看到的 IoC容器初始化 的过程是一致的。 ```java public abstract class FrameworkServlet extends HttpServletBean { - /** - * 为此 servlet 实例化一个 WebApplicationContext,可以是默认的 XmlWebApplicationContext, - * 也可以是用户设置的自定义 Context上下文 - */ - protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) { - return createWebApplicationContext((ApplicationContext) parent); - } - - protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { - // 默认为 XmlWebApplicationContext.class - Class contextClass = getContextClass(); - if (this.logger.isDebugEnabled()) { - this.logger.debug("Servlet with name '" + getServletName() + - "' will try to create custom WebApplicationContext context of class '" + - contextClass.getName() + "'" + ", using parent context [" + parent + "]"); - } - if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { - throw new ApplicationContextException( - "Fatal initialization error in servlet with name '" + getServletName() + - "': custom WebApplicationContext class [" + contextClass.getName() + - "] is not of type ConfigurableWebApplicationContext"); - } - // 实例化需要的上下文对象,并为其设置属性 - ConfigurableWebApplicationContext wac = - (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); - - wac.setEnvironment(getEnvironment()); - // 这里设置的 双亲上下文,就是在 ContextLoader 中建立的根上下文 - wac.setParent(parent); - wac.setConfigLocation(getContextConfigLocation()); - - // 配置并且刷新 WebApplicationContext对象 - configureAndRefreshWebApplicationContext(wac); - - return wac; - } - - protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { - if (ObjectUtils.identityToString(wac).equals(wac.getId())) { - // 应用程序上下文id 仍设置为其原始默认值,如果该 id 不为空的话 - if (this.contextId != null) { - wac.setId(this.contextId); - } - else { - // 生成默认的 id - ServletContext sc = getServletContext(); - if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) { - // 当 Servlet <= 2.4:如果有,请使用 web.xml 中指定的名称。 - String servletContextName = sc.getServletContextName(); - if (servletContextName != null) { - wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContextName + - "." + getServletName()); - } - else { - wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + getServletName()); - } - } - else { - // Servlet 2.5 的 getContextPath 可用! - wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + - ObjectUtils.getDisplayString(sc.getContextPath()) + "/" + getServletName()); - } - } - } - - // 设置其它配置信息 - wac.setServletContext(getServletContext()); - wac.setServletConfig(getServletConfig()); - wac.setNamespace(getNamespace()); - wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener())); - - // 在刷新上下文的任何情况下,都将会调用 此wac 的 env的 initPropertySources()方法。 - // 在此处执行此方法,以确保在刷新上下文之前,servlet属性源 已准备就绪 - ConfigurableEnvironment env = wac.getEnvironment(); - if (env instanceof ConfigurableWebEnvironment) { - ((ConfigurableWebEnvironment)env).initPropertySources(getServletContext(), getServletConfig()); - } - - postProcessWebApplicationContext(wac); - - applyInitializers(wac); - - // IoC容器 都是通过该方法完成 容器初始化的 - wac.refresh(); - } + /** + * 为此 servlet 实例化一个 WebApplicationContext,可以是默认的 XmlWebApplicationContext, + * 也可以是用户设置的自定义 Context上下文 + */ + protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) { + return createWebApplicationContext((ApplicationContext) parent); + } + + protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { + // 默认为 XmlWebApplicationContext.class + Class contextClass = getContextClass(); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Servlet with name '" + getServletName() + + "' will try to create custom WebApplicationContext context of class '" + + contextClass.getName() + "'" + ", using parent context [" + parent + "]"); + } + if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { + throw new ApplicationContextException( + "Fatal initialization error in servlet with name '" + getServletName() + + "': custom WebApplicationContext class [" + contextClass.getName() + + "] is not of type ConfigurableWebApplicationContext"); + } + // 实例化需要的上下文对象,并为其设置属性 + ConfigurableWebApplicationContext wac = + (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); + + wac.setEnvironment(getEnvironment()); + // 这里设置的 双亲上下文,就是在 ContextLoader 中建立的根上下文 + wac.setParent(parent); + wac.setConfigLocation(getContextConfigLocation()); + + // 配置并且刷新 WebApplicationContext对象 + configureAndRefreshWebApplicationContext(wac); + + return wac; + } + + protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { + if (ObjectUtils.identityToString(wac).equals(wac.getId())) { + // 应用程序上下文id 仍设置为其原始默认值,如果该 id 不为空的话 + if (this.contextId != null) { + wac.setId(this.contextId); + } + else { + // 生成默认的 id + ServletContext sc = getServletContext(); + if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) { + // 当 Servlet <= 2.4:如果有,请使用 web.xml 中指定的名称。 + String servletContextName = sc.getServletContextName(); + if (servletContextName != null) { + wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContextName + + "." + getServletName()); + } + else { + wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + getServletName()); + } + } + else { + // Servlet 2.5 的 getContextPath 可用! + wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + + ObjectUtils.getDisplayString(sc.getContextPath()) + "/" + getServletName()); + } + } + } + + // 设置其它配置信息 + wac.setServletContext(getServletContext()); + wac.setServletConfig(getServletConfig()); + wac.setNamespace(getNamespace()); + wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener())); + + // 在刷新上下文的任何情况下,都将会调用 此wac 的 env的 initPropertySources()方法。 + // 在此处执行此方法,以确保在刷新上下文之前,servlet属性源 已准备就绪 + ConfigurableEnvironment env = wac.getEnvironment(); + if (env instanceof ConfigurableWebEnvironment) { + ((ConfigurableWebEnvironment)env).initPropertySources(getServletContext(), getServletConfig()); + } + + postProcessWebApplicationContext(wac); + + applyInitializers(wac); + + // IoC容器 都是通过该方法完成 容器初始化的 + wac.refresh(); + } } ``` 这时候 DispatcherServlet 中的 IoC容器 已经建立起来了,这个 IoC容器 是 根上下文 的子容器。如果要查找一个由 DispatcherServlet 所持有的 IoC容器 来管理的 Bean,系统会首先到 根上下文 中去查找。如果查找不到,才会到 DispatcherServlet 所管理的 IoC容器 去进行查找,这是由 IoC容器 的 getBean() 的实现来决定的。通过一系列在 Web容器 中执行的动作,在这个上下文体系建立和初始化完毕的基础上,SpringMVC 就可以发挥其作用了。下面来分析一下 SpringMVC 的具体实现。 @@ -297,76 +297,76 @@ public abstract class FrameworkServlet extends HttpServletBean { 在 DispatcherServlet 的初始化过程中,以对 HandlerMapping 的初始化调用作为触发点,了解 SpringMVC模块 初始化的方法调用关系。这个调用关系最初是由 HttpServletBean 的 init()方法 触发的,这个 HttpServletBean 是 HttpServlet 的子类。接着会在 HttpServletBean 的子类 FrameworkServlet 中对 IoC容器 完成初始化,在这个初始化方法中,会调用 DispatcherServlet 的 initStrategies()方法,该方法包括对各种 MVC框架 的实现元素,比如支持国际化的 LocalResolver、支持 request 映射的 HandlerMappings,以及视图生成的 ViewResolver 等。由该方法启动整个 SpringMVC框架 的初始化。 ```java public class DispatcherServlet extends FrameworkServlet { - /** - * 初始化此 servlet 使用的策略对象。 - * 可以在子类中重写,以便初始化进一步的策略对象(U8C) - */ - protected void initStrategies(ApplicationContext context) { - // 请求解析 - initMultipartResolver(context); - // 多语言,国际化 - initLocaleResolver(context); - // 主题view层 - initThemeResolver(context); - // 解析 url 和 Method 的对应关系 - initHandlerMappings(context); - // 适配器匹配 - initHandlerAdapters(context); - // 异常解析 - initHandlerExceptionResolvers(context); - // 视图转发,根据视图名字匹配到一个具体模板 - initRequestToViewNameTranslator(context); - // 解析模板中的内容 - initViewResolvers(context); - - initFlashMapManager(context); - } + /** + * 初始化此 servlet 使用的策略对象。 + * 可以在子类中重写,以便初始化进一步的策略对象(U8C) + */ + protected void initStrategies(ApplicationContext context) { + // 请求解析 + initMultipartResolver(context); + // 多语言,国际化 + initLocaleResolver(context); + // 主题view层 + initThemeResolver(context); + // 解析 url 和 Method 的对应关系 + initHandlerMappings(context); + // 适配器匹配 + initHandlerAdapters(context); + // 异常解析 + initHandlerExceptionResolvers(context); + // 视图转发,根据视图名字匹配到一个具体模板 + initRequestToViewNameTranslator(context); + // 解析模板中的内容 + initViewResolvers(context); + + initFlashMapManager(context); + } } ``` 对于具体的初始化过程,根据上面的方法名称,很容易理解。以 HandlerMapping 为例来说明这个 initHandlerMappings()过程。这里的 Mapping关系 的作用是,为 HTTP请求 找到相应的 Controller控制器,从而利用这些 控制器Controller 去完成设计好的数据处理工作。 HandlerMappings 完成对 MVC 中 Controller 的定义和配置,只不过在 Web 这个特定的应用环境中,这些控制器是与具体的 HTTP请求 相对应的。在 HandlerMapping初始化 的过程中,把在 Bean配置文件 中配置好的 HandlerMapping 从 IoC容器 中取得。 ```java - /** - * 初始化此类使用的 HandlerMappings。 - * 如果在 BeanFactory 中没有为此命名空间定义的 HandlerMapping bean,则默认为 BeanNameUrlHandlerMapping - */ - private void initHandlerMappings(ApplicationContext context) { - this.handlerMappings = null; - - // 这个 detectAllHandlerMappings 默认为 true,表示从所有的 IoC容器 中获取所有的HandlerMappings - if (this.detectAllHandlerMappings) { - // 查找所有的 HandlerMapping,从 应用上下文context 及其双亲上下文中 - Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( - context, HandlerMapping.class, true, false); - if (!matchingBeans.isEmpty()) { - this.handlerMappings = new ArrayList( - matchingBeans.values()); - // 保持 HandlerMappings 的有序性 - OrderComparator.sort(this.handlerMappings); - } - } - else { - try { - // 根据名称从当前的 IoC容器 中通过 getBean() 获 取HandlerMapping - HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, - HandlerMapping.class); - this.handlerMappings = Collections.singletonList(hm); - } - catch (NoSuchBeanDefinitionException ex) { - // 忽略,稍后将添加默认的 HandlerMapping - } - } - - // 如果找不到其他映射,请通过注册默认的 HandlerMapping 确保至少有一个 HandlerMapping - if (this.handlerMappings == null) { - this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); - if (logger.isDebugEnabled()) { - logger.debug("No HandlerMappings found in servlet '" + getServletName() - + "': using default"); - } - } - } + /** + * 初始化此类使用的 HandlerMappings。 + * 如果在 BeanFactory 中没有为此命名空间定义的 HandlerMapping bean,则默认为 BeanNameUrlHandlerMapping + */ + private void initHandlerMappings(ApplicationContext context) { + this.handlerMappings = null; + + // 这个 detectAllHandlerMappings 默认为 true,表示从所有的 IoC容器 中获取所有的HandlerMappings + if (this.detectAllHandlerMappings) { + // 查找所有的 HandlerMapping,从 应用上下文context 及其双亲上下文中 + Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( + context, HandlerMapping.class, true, false); + if (!matchingBeans.isEmpty()) { + this.handlerMappings = new ArrayList( + matchingBeans.values()); + // 保持 HandlerMappings 的有序性 + OrderComparator.sort(this.handlerMappings); + } + } + else { + try { + // 根据名称从当前的 IoC容器 中通过 getBean() 获 取HandlerMapping + HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, + HandlerMapping.class); + this.handlerMappings = Collections.singletonList(hm); + } + catch (NoSuchBeanDefinitionException ex) { + // 忽略,稍后将添加默认的 HandlerMapping + } + } + + // 如果找不到其他映射,请通过注册默认的 HandlerMapping 确保至少有一个 HandlerMapping + if (this.handlerMappings == null) { + this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); + if (logger.isDebugEnabled()) { + logger.debug("No HandlerMappings found in servlet '" + getServletName() + + "': using default"); + } + } + } ``` 经过以上读取过程,handlerMappings变量 就已经获取了在 Bean 中配置好的映射关系。其他的初始化过程和 handlerMappings 比较类似,都是直接从 IoC容器 中读入配置,所以这里的 MVC初始化过程 是建立在 IoC容器 已经初始化完成的基础上的。 @@ -383,22 +383,22 @@ HandlerMappings 完成对 MVC 中 Controller 的定义和配置,只不过在 W ```java public interface HandlerMapping { - String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"; - - String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; - - String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; - - String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"; - - String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables"; - - String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; - - /** - * 返回的这个 HandlerExecutionChain 不但持有 handler本身,还包括了处理这个 HTTP请求 的拦截器链 - */ - HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; + String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"; + + String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; + + String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; + + String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"; + + String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables"; + + String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; + + /** + * 返回的这个 HandlerExecutionChain 不但持有 handler本身,还包括了处理这个 HTTP请求 的拦截器链 + */ + HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; } ``` @@ -406,92 +406,92 @@ public interface HandlerMapping { ```java public class HandlerExecutionChain { - private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class); - - private final Object handler; - - private HandlerInterceptor[] interceptors; - - private List interceptorList; - - private int interceptorIndex = -1; - - - public HandlerExecutionChain(Object handler) { - this(handler, null); - } - - public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) { - if (handler instanceof HandlerExecutionChain) { - HandlerExecutionChain originalChain = (HandlerExecutionChain) handler; - this.handler = originalChain.getHandler(); - this.interceptorList = new ArrayList(); - CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList); - CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList); - } - else { - this.handler = handler; - this.interceptors = interceptors; - } - } - - public Object getHandler() { - return this.handler; - } - - /** - * 为拦截器链 添加拦截器 - */ - public void addInterceptor(HandlerInterceptor interceptor) { - initInterceptorList(); - this.interceptorList.add(interceptor); - } - - /** - * 批量添加拦截器 - */ - public void addInterceptors(HandlerInterceptor[] interceptors) { - if (interceptors != null) { - initInterceptorList(); - this.interceptorList.addAll(Arrays.asList(interceptors)); - } - } - - /** - * 延迟初始化 interceptorList 和 interceptors集合 - */ - private void initInterceptorList() { - if (this.interceptorList == null) { - this.interceptorList = new ArrayList(); - } - if (this.interceptors != null) { - this.interceptorList.addAll(Arrays.asList(this.interceptors)); - this.interceptors = null; - } - } - - public HandlerInterceptor[] getInterceptors() { - if (this.interceptors == null && this.interceptorList != null) { - this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]); - } - return this.interceptors; - } - - @Override - public String toString() { - if (this.handler == null) { - return "HandlerExecutionChain with no handler"; - } - StringBuilder sb = new StringBuilder(); - sb.append("HandlerExecutionChain with handler [").append(this.handler).append("]"); - if (!CollectionUtils.isEmpty(this.interceptorList)) { - sb.append(" and ").append(this.interceptorList.size()).append(" interceptor"); - if (this.interceptorList.size() > 1) { - sb.append("s"); - } - } - return sb.toString(); - } + private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class); + + private final Object handler; + + private HandlerInterceptor[] interceptors; + + private List interceptorList; + + private int interceptorIndex = -1; + + + public HandlerExecutionChain(Object handler) { + this(handler, null); + } + + public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) { + if (handler instanceof HandlerExecutionChain) { + HandlerExecutionChain originalChain = (HandlerExecutionChain) handler; + this.handler = originalChain.getHandler(); + this.interceptorList = new ArrayList(); + CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList); + CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList); + } + else { + this.handler = handler; + this.interceptors = interceptors; + } + } + + public Object getHandler() { + return this.handler; + } + + /** + * 为拦截器链 添加拦截器 + */ + public void addInterceptor(HandlerInterceptor interceptor) { + initInterceptorList(); + this.interceptorList.add(interceptor); + } + + /** + * 批量添加拦截器 + */ + public void addInterceptors(HandlerInterceptor[] interceptors) { + if (interceptors != null) { + initInterceptorList(); + this.interceptorList.addAll(Arrays.asList(interceptors)); + } + } + + /** + * 延迟初始化 interceptorList 和 interceptors集合 + */ + private void initInterceptorList() { + if (this.interceptorList == null) { + this.interceptorList = new ArrayList(); + } + if (this.interceptors != null) { + this.interceptorList.addAll(Arrays.asList(this.interceptors)); + this.interceptors = null; + } + } + + public HandlerInterceptor[] getInterceptors() { + if (this.interceptors == null && this.interceptorList != null) { + this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]); + } + return this.interceptors; + } + + @Override + public String toString() { + if (this.handler == null) { + return "HandlerExecutionChain with no handler"; + } + StringBuilder sb = new StringBuilder(); + sb.append("HandlerExecutionChain with handler [").append(this.handler).append("]"); + if (!CollectionUtils.isEmpty(this.interceptorList)) { + sb.append(" and ").append(this.interceptorList.size()).append(" interceptor"); + if (this.interceptorList.size() > 1) { + sb.append("s"); + } + } + return sb.toString(); + } } ``` HandlerExecutionChain 中定义的 Handler 和 HandlerInterceptor[]属性 需要在定义 HandlerMapping 时配置好,例如对具体的 SimpleURLHandlerMapping,要做的就是根据 URL映射 的方式,注册 Handler 和 HandlerInterceptor[],从而维护一个反映这种映射关系的 handlerMap。当需要匹配 HTTP请求 时,需要查询这个 handlerMap 中的信息来得到对应的 HandlerExecutionChain。这些信息是什么时候配置好的呢?这里有一个注册过程,这个注册过程在容器对 Bean 进行依赖注入时发生,它实际上是通过一个 Bean 的 postProcessor() 来完成的。以 SimpleHandlerMapping 为例,需要注意的是,这里用到了对容器的回调,只有 SimpleHandlerMapping 是 ApplicationContextAware 的子类才能启动这个注册过程。这个注册过程完成的是反映 URL 和 Controller 之间映射关系的 handlerMap 的建立。 @@ -501,124 +501,124 @@ HandlerExecutionChain 中定义的 Handler 和 HandlerInterceptor[]属性 需要 ```java public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { - @Override - public void initApplicationContext() throws BeansException { - super.initApplicationContext(); - registerHandlers(this.urlMap); - } - - /** - * 为相应的路径注册 URL映射 中指定的所有 handlers处理程序 - */ - protected void registerHandlers(Map urlMap) throws BeansException { - if (urlMap.isEmpty()) { - logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); - } - else { - // 这里对 bean 的配置进行解析,然后调用父类的 registerHandler()方法 进行解析 - for (Map.Entry entry : urlMap.entrySet()) { - String url = entry.getKey(); - Object handler = entry.getValue(); - // 如果 url 没有斜线,就在前面加上斜线 - if (!url.startsWith("/")) { - url = "/" + url; - } - // Remove whitespace from handler bean name. - if (handler instanceof String) { - handler = ((String) handler).trim(); - } - // 这里调用的是父类的方法 - registerHandler(url, handler); - } - } - } + @Override + public void initApplicationContext() throws BeansException { + super.initApplicationContext(); + registerHandlers(this.urlMap); + } + + /** + * 为相应的路径注册 URL映射 中指定的所有 handlers处理程序 + */ + protected void registerHandlers(Map urlMap) throws BeansException { + if (urlMap.isEmpty()) { + logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping"); + } + else { + // 这里对 bean 的配置进行解析,然后调用父类的 registerHandler()方法 进行解析 + for (Map.Entry entry : urlMap.entrySet()) { + String url = entry.getKey(); + Object handler = entry.getValue(); + // 如果 url 没有斜线,就在前面加上斜线 + if (!url.startsWith("/")) { + url = "/" + url; + } + // Remove whitespace from handler bean name. + if (handler instanceof String) { + handler = ((String) handler).trim(); + } + // 这里调用的是父类的方法 + registerHandler(url, handler); + } + } + } } ``` 这个 SimpleUrlHandlerMapping 注册过程的完成,很大一部分需要它的基类来配合,这个基类就是 AbstractUrlHandlerMapping。在 AbstractUrlHandlerMapping 的处理过程中,如果使用 Bean 的名称作为映射,那么直接从容器中获取这个 HTTP映射 对应的 Bean,然后还要对不同的 URL配置 进行解析处理,比如在 HTTP请求 中配置成 “/” 和 通配符“/*” 的 URL,以及正常的 URL请求,完成这个解析处理过程以后,会把 URL 和 handler 作为键值对放到一个 handlerMap 中去。 ```java public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { - /** - * 为给定的 URL路径 注册指定的 handler处理程序 - */ - 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); - } - } - - /** - * 为给定的 URL路径 注册指定的 handler处理程序 - */ - protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { - Assert.notNull(urlPath, "URL path must not be null"); - Assert.notNull(handler, "Handler object must not be null"); - Object resolvedHandler = handler; - - // 如果使用 bean名称 进行映射,就直接从 IoC容器 中获取该 bean名称 对应的 handler - if (!this.lazyInitHandlers && handler instanceof String) { - String handlerName = (String) handler; - if (getApplicationContext().isSingleton(handlerName)) { - resolvedHandler = getApplicationContext().getBean(handlerName); - } - } - - Object mappedHandler = this.handlerMap.get(urlPath); - if (mappedHandler != null) { - if (mappedHandler != resolvedHandler) { - throw new IllegalStateException( - "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath + - "]: There is already " + getHandlerDescription(mappedHandler) + " mapped."); - } - } - else { - // 处理 URL 是 "/" 的映射,把这个 "/" 映射的 controller 设置到 rootHandler 中 - if (urlPath.equals("/")) { - if (logger.isInfoEnabled()) { - logger.info("Root mapping to " + getHandlerDescription(handler)); - } - setRootHandler(resolvedHandler); - } - // 处理 URL 是 "/" 的映射,把这个 "/" 映射的 controller 设置到 defaultHandler 中 - else if (urlPath.equals("/*")) { - if (logger.isInfoEnabled()) { - logger.info("Default mapping to " + getHandlerDescription(handler)); - } - setDefaultHandler(resolvedHandler); - } - // 处理正常的 URL映射,此 handlerMap 的 key 和 value 分别代表 URL 和 映射的Controller - else { - this.handlerMap.put(urlPath, resolvedHandler); - if (logger.isInfoEnabled()) { - logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler)); - } - } - } - } - - /** - * 为此 handler映射 设置 根handler,即要为根路径("/")注册的 handler - *

Default is {@code null}, indicating no root handler. - */ - public void setRootHandler(Object rootHandler) { - this.rootHandler = rootHandler; - } - - public Object getRootHandler() { - return this.rootHandler; - } - - /** - * 设置 此handler映射 的默认 handler。如果未找到特定映射,则将返回 此handler - */ - public void setDefaultHandler(Object defaultHandler) { - this.defaultHandler = defaultHandler; - } - - public Object getDefaultHandler() { - return this.defaultHandler; - } + /** + * 为给定的 URL路径 注册指定的 handler处理程序 + */ + 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); + } + } + + /** + * 为给定的 URL路径 注册指定的 handler处理程序 + */ + protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { + Assert.notNull(urlPath, "URL path must not be null"); + Assert.notNull(handler, "Handler object must not be null"); + Object resolvedHandler = handler; + + // 如果使用 bean名称 进行映射,就直接从 IoC容器 中获取该 bean名称 对应的 handler + if (!this.lazyInitHandlers && handler instanceof String) { + String handlerName = (String) handler; + if (getApplicationContext().isSingleton(handlerName)) { + resolvedHandler = getApplicationContext().getBean(handlerName); + } + } + + Object mappedHandler = this.handlerMap.get(urlPath); + if (mappedHandler != null) { + if (mappedHandler != resolvedHandler) { + throw new IllegalStateException( + "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath + + "]: There is already " + getHandlerDescription(mappedHandler) + " mapped."); + } + } + else { + // 处理 URL 是 "/" 的映射,把这个 "/" 映射的 controller 设置到 rootHandler 中 + if (urlPath.equals("/")) { + if (logger.isInfoEnabled()) { + logger.info("Root mapping to " + getHandlerDescription(handler)); + } + setRootHandler(resolvedHandler); + } + // 处理 URL 是 "/" 的映射,把这个 "/" 映射的 controller 设置到 defaultHandler 中 + else if (urlPath.equals("/*")) { + if (logger.isInfoEnabled()) { + logger.info("Default mapping to " + getHandlerDescription(handler)); + } + setDefaultHandler(resolvedHandler); + } + // 处理正常的 URL映射,此 handlerMap 的 key 和 value 分别代表 URL 和 映射的Controller + else { + this.handlerMap.put(urlPath, resolvedHandler); + if (logger.isInfoEnabled()) { + logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler)); + } + } + } + } + + /** + * 为此 handler映射 设置 根handler,即要为根路径("/")注册的 handler + *

Default is {@code null}, indicating no root handler. + */ + public void setRootHandler(Object rootHandler) { + this.rootHandler = rootHandler; + } + + public Object getRootHandler() { + return this.rootHandler; + } + + /** + * 设置 此handler映射 的默认 handler。如果未找到特定映射,则将返回 此handler + */ + public void setDefaultHandler(Object defaultHandler) { + this.defaultHandler = defaultHandler; + } + + public Object getDefaultHandler() { + return this.defaultHandler; + } } ``` 这里的 handlerMap 是一个 HashMap,其中保存了 “URL请求” --> “Controller对象” 的映射关系,这个 handlerMap 是在 AbstractUrlHandlerMapping 中定义的( Map handlerMap = new LinkedHashMap() ),这个配置好 URL请求 和 handler映射数据 的 handlerMap,为 SpringMVC 响应 HTTP请求 准备好了基本的映射数据,根据这个 handlerMap 以及设置于其中的映射数据,可以方便地由 URL请求 得到它所对应的 handler。有了这些准备工作,SpringMVC 就可以等待 HTTP请求 的到来了。 @@ -627,134 +627,134 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport 继续通过 SimpleUrlHandlerMapping的实现 来分析 HandlerMapping 的 接口方法getHandler(),该方法会根据初始化时得到的映射关系来生成 DispatcherServlet 需要的 HandlerExecutionChain,也就是说,这个 getHandler()方法 是实际使用 HandlerMapping 完成请求的映射处理的地方。在前面的 HandlerExecutionChain 的执行过程中,首先在 AbstractHandlerMapping 中启动 getHandler() 的调用。 ```java public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { - /** - * 查找给定请求的 handler,如果找不到特定的 handler,则返回到 defaultHandler - */ - public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { - // 这里用到了模板方法模式,getHandler() 是一个模板方法,定义了流程,getHandlerInternal() 则是 - // 一个抽象方法,交由子类实现 - Object handler = getHandlerInternal(request); - // 如果找不到特定的 handler,则取 defaultHandler - if (handler == null) { - handler = getDefaultHandler(); - } - // defaultHandler 也没有则返回 null - if (handler == null) { - return null; - } - // 如果该 handler 是 String类型的,说明它是一个 beanName - // 根据该 beanName 从 IoC容器 中获取真正的 handler对象 - if (handler instanceof String) { - String handlerName = (String) handler; - handler = getApplicationContext().getBean(handlerName); - } - // 这里把 handler 添加到到 HandlerExecutionChain 中 - return getHandlerExecutionChain(handler, request); - } + /** + * 查找给定请求的 handler,如果找不到特定的 handler,则返回到 defaultHandler + */ + public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { + // 这里用到了模板方法模式,getHandler() 是一个模板方法,定义了流程,getHandlerInternal() 则是 + // 一个抽象方法,交由子类实现 + Object handler = getHandlerInternal(request); + // 如果找不到特定的 handler,则取 defaultHandler + if (handler == null) { + handler = getDefaultHandler(); + } + // defaultHandler 也没有则返回 null + if (handler == null) { + return null; + } + // 如果该 handler 是 String类型的,说明它是一个 beanName + // 根据该 beanName 从 IoC容器 中获取真正的 handler对象 + if (handler instanceof String) { + String handlerName = (String) handler; + handler = getApplicationContext().getBean(handlerName); + } + // 这里把 handler 添加到到 HandlerExecutionChain 中 + return getHandlerExecutionChain(handler, request); + } } ``` 取得 handler 的具体过程在 getHandlerInternal()方法 中实现,这个方法接受 HTTP请求 作为参数,它的实现在 AbstractHandlerMapping 的子类 AbstractUrlHandlerMapping 中,这个实现过程包括从 HTTP请求 中得到 URL,并根据 URL 到 urlMapping 中获得 handler。 ```java public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { - /** - * 查找 给定请求的URL 对应的 handler - */ - @Override - protected Object getHandlerInternal(HttpServletRequest request) throws Exception { - // 从 request 中获取请求的 URL路径 - String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); - // 将得到的 URL路径 与 handler 进行匹配,得到对应的 handler,如果没有对应的 handler - // 则返回 null,这样 默认的handler 会被使用 - Object handler = lookupHandler(lookupPath, request); - if (handler == null) { - // We need to care for the default handler directly, since we need to - // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well. - Object rawHandler = null; - if ("/".equals(lookupPath)) { - rawHandler = getRootHandler(); - } - // 使用 默认的handler - if (rawHandler == null) { - rawHandler = getDefaultHandler(); - } - if (rawHandler != null) { - // Bean name or resolved handler? - if (rawHandler instanceof String) { - String handlerName = (String) rawHandler; - rawHandler = getApplicationContext().getBean(handlerName); - } - validateHandler(rawHandler, request); - handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); - } - } - if (handler != null && logger.isDebugEnabled()) { - logger.debug("Mapping [" + lookupPath + "] to " + handler); - } - else if (handler == null && logger.isTraceEnabled()) { - logger.trace("No handler mapping found for [" + lookupPath + "]"); - } - return handler; - } - - /** - * 查找给定 URL路径 的 handler实例 - */ - protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { - // 直接匹配 - Object handler = this.handlerMap.get(urlPath); - if (handler != null) { - // Bean name or resolved handler? - if (handler instanceof String) { - String handlerName = (String) handler; - handler = getApplicationContext().getBean(handlerName); - } - validateHandler(handler, request); - return buildPathExposingHandler(handler, urlPath, urlPath, null); - } - // 正则匹配 - List matchingPatterns = new ArrayList(); - for (String registeredPattern : this.handlerMap.keySet()) { - if (getPathMatcher().match(registeredPattern, urlPath)) { - matchingPatterns.add(registeredPattern); - } - } - String bestPatternMatch = null; - Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath); - if (!matchingPatterns.isEmpty()) { - Collections.sort(matchingPatterns, patternComparator); - if (logger.isDebugEnabled()) { - logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns); - } - bestPatternMatch = matchingPatterns.get(0); - } - if (bestPatternMatch != null) { - handler = this.handlerMap.get(bestPatternMatch); - // Bean name or resolved handler? - if (handler instanceof String) { - String handlerName = (String) handler; - handler = getApplicationContext().getBean(handlerName); - } - validateHandler(handler, request); - String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); - - // There might be multiple 'best patterns', let's make sure we have the correct URI template variables - // for all of them - Map uriTemplateVariables = new LinkedHashMap(); - for (String matchingPattern : matchingPatterns) { - if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { - Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); - Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars); - uriTemplateVariables.putAll(decodedVars); - } - } - if (logger.isDebugEnabled()) { - logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables); - } - return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); - } - // No handler found... - return null; - } + /** + * 查找 给定请求的URL 对应的 handler + */ + @Override + protected Object getHandlerInternal(HttpServletRequest request) throws Exception { + // 从 request 中获取请求的 URL路径 + String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); + // 将得到的 URL路径 与 handler 进行匹配,得到对应的 handler,如果没有对应的 handler + // 则返回 null,这样 默认的handler 会被使用 + Object handler = lookupHandler(lookupPath, request); + if (handler == null) { + // We need to care for the default handler directly, since we need to + // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well. + Object rawHandler = null; + if ("/".equals(lookupPath)) { + rawHandler = getRootHandler(); + } + // 使用 默认的handler + if (rawHandler == null) { + rawHandler = getDefaultHandler(); + } + if (rawHandler != null) { + // Bean name or resolved handler? + if (rawHandler instanceof String) { + String handlerName = (String) rawHandler; + rawHandler = getApplicationContext().getBean(handlerName); + } + validateHandler(rawHandler, request); + handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); + } + } + if (handler != null && logger.isDebugEnabled()) { + logger.debug("Mapping [" + lookupPath + "] to " + handler); + } + else if (handler == null && logger.isTraceEnabled()) { + logger.trace("No handler mapping found for [" + lookupPath + "]"); + } + return handler; + } + + /** + * 查找给定 URL路径 的 handler实例 + */ + protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { + // 直接匹配 + Object handler = this.handlerMap.get(urlPath); + if (handler != null) { + // Bean name or resolved handler? + if (handler instanceof String) { + String handlerName = (String) handler; + handler = getApplicationContext().getBean(handlerName); + } + validateHandler(handler, request); + return buildPathExposingHandler(handler, urlPath, urlPath, null); + } + // 正则匹配 + List matchingPatterns = new ArrayList(); + for (String registeredPattern : this.handlerMap.keySet()) { + if (getPathMatcher().match(registeredPattern, urlPath)) { + matchingPatterns.add(registeredPattern); + } + } + String bestPatternMatch = null; + Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath); + if (!matchingPatterns.isEmpty()) { + Collections.sort(matchingPatterns, patternComparator); + if (logger.isDebugEnabled()) { + logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns); + } + bestPatternMatch = matchingPatterns.get(0); + } + if (bestPatternMatch != null) { + handler = this.handlerMap.get(bestPatternMatch); + // Bean name or resolved handler? + if (handler instanceof String) { + String handlerName = (String) handler; + handler = getApplicationContext().getBean(handlerName); + } + validateHandler(handler, request); + String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); + + // There might be multiple 'best patterns', let's make sure we have the correct URI template variables + // for all of them + Map uriTemplateVariables = new LinkedHashMap(); + for (String matchingPattern : matchingPatterns) { + if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { + Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); + Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars); + uriTemplateVariables.putAll(decodedVars); + } + } + if (logger.isDebugEnabled()) { + logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables); + } + return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); + } + // No handler found... + return null; + } } ``` 经过这一系列对 HTTP请求 进行解析和匹配 handler 的过程,得到了与请求对应的 handler处理器。在返回的 handler 中,已经完成了在 HandlerExecutionChain 中进行封装的工作,为 handler 对 HTTP请求 的响应做好了准备。 @@ -764,248 +764,248 @@ DispatcherServlet 是 SpringMVC框架 中非常重要的一个类,不但建立 ```java public class DispatcherServlet extends FrameworkServlet { - /** 此 DispatcherServlet 使用的 HandlerMapping对象列表 */ - private List handlerMappings; - - /** 此 DispatcherServlet 使用的 HandlerAdapter对象列表 */ - private List handlerAdapters; - - - /** - * 公开 DispatcherServlet 特定的请求属性,并将其委托给 doDispatch()方法 进行实际的分发 - */ - @Override - protected void doService(HttpServletRequest request, HttpServletResponse response) - throws Exception { - if (logger.isDebugEnabled()) { - // 得到 请求的URI - String requestUri = urlPathHelper.getRequestUri(request); - String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() - ? " resumed" : ""; - logger.debug("DispatcherServlet with name '" + getServletName() + "'" - + resumed + " processing " + request.getMethod() + " request for [" - + requestUri + "]"); - } - - // Keep a snapshot of the request attributes in case of an include, - // to be able to restore the original attributes after the include. - Map attributesSnapshot = null; - if (WebUtils.isIncludeRequest(request)) { - logger.debug("Taking snapshot of request attributes before include"); - attributesSnapshot = new HashMap(); - Enumeration attrNames = request.getAttributeNames(); - while (attrNames.hasMoreElements()) { - String attrName = (String) attrNames.nextElement(); - if (this.cleanupAfterInclude - || attrName.startsWith("org.springframework.web.servlet")) { - 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()); - - 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()) { - return; - } - // Restore the original attribute snapshot, in case of an include. - if (attributesSnapshot != null) { - restoreAttributesAfterInclude(request, attributesSnapshot); - } - } - } - - /** - * 中央控制器,控制请求的转发 - * 对请求的处理实际上是由 doDispatch() 来完成的,它是 DispatcherServlet 完成 HTTP请求 分发处理的主要方法, - * 包括准备 ModelAndView,调用 getHandler()方法 来响应 HTTP请求,然后通过执行 Handler的处理 来获取请求的 - * 处理结果,最后把结果返回出去 - */ - 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,这个 ModelAndView 持有 handler处理请求的结果 - ModelAndView mv = null; - Exception dispatchException = null; - - try { - // 1.检查是否是文件上传的请求 - processedRequest = checkMultipart(request); - multipartRequestParsed = processedRequest != request; - - // 2.取得处理当前请求的 Controller对象,这里也称为 hanlder处理器,这里并不是 - // 直接返回 controller对象,而是返回的 HandlerExecutionChain请求处理器链对象, - // 该对象封装了 handler 和 interceptors - mappedHandler = getHandler(processedRequest, false); - // 如果 handler 为空,则返回 404 - if (mappedHandler == null || mappedHandler.getHandler() == null) { - noHandlerFound(processedRequest, response); - return; - } - - // 3. 获取处理 request 的处理器适配器 HandlerAdapter - HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); - - // 获取 请求方式,如:GET, POST, PUT - String method = request.getMethod(); - boolean isGet = "GET".equals(method); - if (isGet || "HEAD".equals(method)) { - - long lastModified = ha.getLastModified(request, - mappedHandler.getHandler()); - if (logger.isDebugEnabled()) { - String requestUri = urlPathHelper.getRequestUri(request); - logger.debug("Last-Modified value for [" + requestUri + "] is: " - + lastModified); - } - if (new ServletWebRequest(request, response).checkNotModified( - lastModified) && isGet) { - return; - } - } - - // 4.拦截器的预处理方法 - if (!mappedHandler.applyPreHandle(processedRequest, response)) { - return; - } - - try { - // 5.实际的处理器处理请求,返回结果视图对象 - mv = ha.handle(processedRequest, response, - mappedHandler.getHandler()); - } - finally { - if (asyncManager.isConcurrentHandlingStarted()) { - return; - } - } - - // 结果视图对象的处理 - applyDefaultViewName(request, mv); - // 6.拦截器的后处理方法 - mappedHandler.applyPostHandle(processedRequest, response, mv); - } - catch (Exception ex) { - dispatchException = ex; - } - processDispatchResult(processedRequest, response, mappedHandler, mv, - dispatchException); - } - catch (Exception ex) { - // 请求成功响应之后的方法 - triggerAfterCompletion(processedRequest, response, mappedHandler, ex); - } - catch (Error err) { - triggerAfterCompletionWithError(processedRequest, response, mappedHandler, - err); - } - finally { - if (asyncManager.isConcurrentHandlingStarted()) { - // Instead of postHandle and afterCompletion - mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, - response); - return; - } - // 清除多部分请求使用的所有资源 - if (multipartRequestParsed) { - cleanupMultipart(processedRequest); - } - } - } - - /** - * 返回此请求的 HandlerExecutionChain,按顺序尝试所有的 HandlerMapping - */ - @Deprecated - protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) - throws Exception { - return getHandler(request); - } - - /** - * 返回此请求的 HandlerExecutionChain - */ - protected HandlerExecutionChain getHandler(HttpServletRequest request) - throws Exception { - // 遍历 此servlet 使用的 HandlerMapping列表 - for (HandlerMapping hm : this.handlerMappings) { - if (logger.isTraceEnabled()) { - logger.trace("Testing handler map [" + hm - + "] in DispatcherServlet with name '" + getServletName() + "'"); - } - // 查找给定请求的 handler - HandlerExecutionChain handler = hm.getHandler(request); - if (handler != null) { - return handler; - } - } - return null; - } - - /** - * 返回 此处理程序对象handler 的 HandlerAdapter - */ - protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { - // 对所有持有的 HandlerAdapter 进行匹配 - for (HandlerAdapter ha : this.handlerAdapters) { - if (logger.isTraceEnabled()) { - logger.trace("Testing handler adapter [" + ha + "]"); - } - if (ha.supports(handler)) { - return ha; - } - } - throw new ServletException("No adapter for handler [" + handler - + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); - } + /** 此 DispatcherServlet 使用的 HandlerMapping对象列表 */ + private List handlerMappings; + + /** 此 DispatcherServlet 使用的 HandlerAdapter对象列表 */ + private List handlerAdapters; + + + /** + * 公开 DispatcherServlet 特定的请求属性,并将其委托给 doDispatch()方法 进行实际的分发 + */ + @Override + protected void doService(HttpServletRequest request, HttpServletResponse response) + throws Exception { + if (logger.isDebugEnabled()) { + // 得到 请求的URI + String requestUri = urlPathHelper.getRequestUri(request); + String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() + ? " resumed" : ""; + logger.debug("DispatcherServlet with name '" + getServletName() + "'" + + resumed + " processing " + request.getMethod() + " request for [" + + requestUri + "]"); + } + + // Keep a snapshot of the request attributes in case of an include, + // to be able to restore the original attributes after the include. + Map attributesSnapshot = null; + if (WebUtils.isIncludeRequest(request)) { + logger.debug("Taking snapshot of request attributes before include"); + attributesSnapshot = new HashMap(); + Enumeration attrNames = request.getAttributeNames(); + while (attrNames.hasMoreElements()) { + String attrName = (String) attrNames.nextElement(); + if (this.cleanupAfterInclude + || attrName.startsWith("org.springframework.web.servlet")) { + 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()); + + 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()) { + return; + } + // Restore the original attribute snapshot, in case of an include. + if (attributesSnapshot != null) { + restoreAttributesAfterInclude(request, attributesSnapshot); + } + } + } + + /** + * 中央控制器,控制请求的转发 + * 对请求的处理实际上是由 doDispatch() 来完成的,它是 DispatcherServlet 完成 HTTP请求 分发处理的主要方法, + * 包括准备 ModelAndView,调用 getHandler()方法 来响应 HTTP请求,然后通过执行 Handler的处理 来获取请求的 + * 处理结果,最后把结果返回出去 + */ + 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,这个 ModelAndView 持有 handler处理请求的结果 + ModelAndView mv = null; + Exception dispatchException = null; + + try { + // 1.检查是否是文件上传的请求 + processedRequest = checkMultipart(request); + multipartRequestParsed = processedRequest != request; + + // 2.取得处理当前请求的 Controller对象,这里也称为 hanlder处理器,这里并不是 + // 直接返回 controller对象,而是返回的 HandlerExecutionChain请求处理器链对象, + // 该对象封装了 handler 和 interceptors + mappedHandler = getHandler(processedRequest, false); + // 如果 handler 为空,则返回 404 + if (mappedHandler == null || mappedHandler.getHandler() == null) { + noHandlerFound(processedRequest, response); + return; + } + + // 3. 获取处理 request 的处理器适配器 HandlerAdapter + HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); + + // 获取 请求方式,如:GET, POST, PUT + String method = request.getMethod(); + boolean isGet = "GET".equals(method); + if (isGet || "HEAD".equals(method)) { + + long lastModified = ha.getLastModified(request, + mappedHandler.getHandler()); + if (logger.isDebugEnabled()) { + String requestUri = urlPathHelper.getRequestUri(request); + logger.debug("Last-Modified value for [" + requestUri + "] is: " + + lastModified); + } + if (new ServletWebRequest(request, response).checkNotModified( + lastModified) && isGet) { + return; + } + } + + // 4.拦截器的预处理方法 + if (!mappedHandler.applyPreHandle(processedRequest, response)) { + return; + } + + try { + // 5.实际的处理器处理请求,返回结果视图对象 + mv = ha.handle(processedRequest, response, + mappedHandler.getHandler()); + } + finally { + if (asyncManager.isConcurrentHandlingStarted()) { + return; + } + } + + // 结果视图对象的处理 + applyDefaultViewName(request, mv); + // 6.拦截器的后处理方法 + mappedHandler.applyPostHandle(processedRequest, response, mv); + } + catch (Exception ex) { + dispatchException = ex; + } + processDispatchResult(processedRequest, response, mappedHandler, mv, + dispatchException); + } + catch (Exception ex) { + // 请求成功响应之后的方法 + triggerAfterCompletion(processedRequest, response, mappedHandler, ex); + } + catch (Error err) { + triggerAfterCompletionWithError(processedRequest, response, mappedHandler, + err); + } + finally { + if (asyncManager.isConcurrentHandlingStarted()) { + // Instead of postHandle and afterCompletion + mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, + response); + return; + } + // 清除多部分请求使用的所有资源 + if (multipartRequestParsed) { + cleanupMultipart(processedRequest); + } + } + } + + /** + * 返回此请求的 HandlerExecutionChain,按顺序尝试所有的 HandlerMapping + */ + @Deprecated + protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) + throws Exception { + return getHandler(request); + } + + /** + * 返回此请求的 HandlerExecutionChain + */ + protected HandlerExecutionChain getHandler(HttpServletRequest request) + throws Exception { + // 遍历 此servlet 使用的 HandlerMapping列表 + for (HandlerMapping hm : this.handlerMappings) { + if (logger.isTraceEnabled()) { + logger.trace("Testing handler map [" + hm + + "] in DispatcherServlet with name '" + getServletName() + "'"); + } + // 查找给定请求的 handler + HandlerExecutionChain handler = hm.getHandler(request); + if (handler != null) { + return handler; + } + } + return null; + } + + /** + * 返回 此处理程序对象handler 的 HandlerAdapter + */ + protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { + // 对所有持有的 HandlerAdapter 进行匹配 + for (HandlerAdapter ha : this.handlerAdapters) { + if (logger.isTraceEnabled()) { + logger.trace("Testing handler adapter [" + ha + "]"); + } + if (ha.supports(handler)) { + return ha; + } + } + throw new ServletException("No adapter for handler [" + handler + + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); + } } ``` 通过判断,可以知道这个 handler 是不是 Controller接口 的实现,比如可以通过具体 HandlerAdapter 的实现来了解这个适配过程。以 SimpleControllerHandlerAdapter的实现 为例来了解这个判断是怎样起作用的。 ```java public class SimpleControllerHandlerAdapter implements HandlerAdapter { - // 判断要执行的 handler 是不是 Controller类型的 - public boolean supports(Object handler) { - return (handler instanceof Controller); - } - - public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - - return ((Controller) handler).handleRequest(request, response); - } - - public long getLastModified(HttpServletRequest request, Object handler) { - if (handler instanceof LastModified) { - return ((LastModified) handler).getLastModified(request); - } - return -1L; - } - + // 判断要执行的 handler 是不是 Controller类型的 + public boolean supports(Object handler) { + return (handler instanceof Controller); + } + + public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + return ((Controller) handler).handleRequest(request, response); + } + + public long getLastModified(HttpServletRequest request, Object handler) { + if (handler instanceof LastModified) { + return ((LastModified) handler).getLastModified(request); + } + return -1L; + } + } ``` 经过上面一系列的处理,得到了 handler对象,接着就可以开始调用 handler对象 中的 HTTP响应动作了。在 handler 中封装了应用业务逻辑,由这些逻辑对 HTTP请求 进行相应的处理,生成需要的数据,并把这些数据封装到 ModelAndView对象 中去,这个 ModelAndView 的数据封装是 SpringMVC框架 的要求。对 handler 来说, 这些都是通过调用 handler()方法 中的 handleRequest()方法 来触发完成的。在得到 ModelAndView对象 以后,这个 ModelAndView对象 会被交给 MVC模式 中的视图类,由视图类对 ModelAndView对象 中的数据进行呈现。