SpringBootWeb应用源码解析
在 Spring 及 Spring Boot 的使用过程中,应用最广泛的当属 Web 应用,而 Web 应用又往往部署在像 Tomcat 这样的 Servlet 容器中。
本章将带领大家学习 Spring Boot 中 Web 应用的整合以及在此过程中与直接使用 Spring 的差别。
遗失的web.xmI
提到 Spring 的 Web 应用,我们首先想到的可能是 Spring MVC 框架和 web.xmI 等配置文件。而 Spring MVC 又是围绕 DispatcherServlet 这个核心类来展开的。
Spring Boot 当前是基于 Spring 5.2.x 版本,和传统的 Spring 启动有所不同。以前是通过在web.xml 中 配 置 Servlet 来 完 成 Spring MVC 的 启 动 , 但 在 Spring Boot 中 是 通 过
Dispatch-erServletAutoConfiguration 来完成初始化工作的。在此过程中,web.xml 遗失了。
我们先回顾一下 Servlet 3.0 之前版本的操作。当我们创建一个 web 项目时,往往会在resources/WEB-INF 目录下创建一个 web.xml 文件, 该文件内配置了 Servlet 和 Filter 等功能。当 Spring MVC 出现后,web.xml 中 便有了 DispatcherServlet 的配置。
随着 Java EE 6 的发布,Servlet 3.0 作为 Java EE 6 规范体系的一员,也被慢慢推广并被用户接受。 Servlet 3.0 在 Servlet 25 的基础. 上提供了一些简化 Web 应用的开发和部署的新特性,无 xml 配置便是其中一项。
Servlet 3.0 提供了@WebServlet、@WebFilter 等注解, 可以使用注解来声明 Servlet 和Filter,这便有了抛弃 web.xml 的基础。同时,它还提供了可以在运行时动态注册 Servlet、Filter、 Listener 等更加强大的功能。 关于动态配置 Servlet,如果翻看 Servlet 3.0 中servlet-api 包下 ServletContext 接口定义的方法,你会看到如下方法定义。
public ServletRegistration. Dynamic addServlet(String servletName, String clas sName);
public ServletRegistration . Dynamic addServlet(String servletName, Servlet s
ervlet);
public ServletRegistration . Dynamic addServlet(String servletName,Class <? e
xtends Servlet> servletClass);public <T extends Servlet> T createServlet(Class<T> clazz)throws ServletExc
eption;
public ServletRegistration getServletRegistration(String servletName);
public Map<String, ? extends ServletRegistration> getServletRegistrations
();
}
在 Servlet 3.0 中还新增了
ServletContainerlnitializer 接口,在容器启动时使用 JAR 服务 API来发现其实现类,并将容器 WEB-INF/ib 目录下 jar 包中的类都交由该类的 onStartup 方法来处理。而 Servlet 和 Filter 在 Web 应用启动时可借助该接口的实现类和 Java 的 SPI 机制完成加载。
在Spring中 提 供 了
ServletContainerlnitializer接 口 的 实 现 类SpringServletContainerlni-tializer, 该 类 在 其 onStartup 方 法 中 会 调 用 所 有WebApplicationInitializer 实现类的 onStartup 方法,将相关组件注册到容器中。而 Servlet和 Filter 也是 通过 WebApplicationitializer 的实现类完成创建和加载的。
基于以上新特性和演变,当我们使用 Spring Boot 时,Spring Boot 已经不知不觉地开始使用这些新特性了。至此,我们从发展的角度了解了 web.xml 消失的过程,在后面的章节我会详细讲解 Spring Boot 是如何进行 Web 应用的自动配置的。
Web应用的自动配置
在 Spring Boot 项目中引入 spring-boot-starter-web 的依赖,Spring Boot 的自动配置机制便会加载并初始化其相关组件。整个自动配置原理在前面章节已经讲过,这里针对 Web 应用再进行一-次梳理。
在上一节中我们已经提到,Servlet3.0 中新增了
ServletContainerlnitializer 接 口 , 而 在 Spring 中 又 提 供 了 其 实 现 类SpringServletContainerlnitializer 来 初 始 化 Servlet 。 但 在 Spring Boot 中 , 当 引 入spring-boot-starter-web 的依赖之后,Spring Boot 并未完全遵守 Servlet 3.0 的规范,也没有使用 Spring 中提供的 SpringServletContainerlnitializer 类,而是完全选择另外一套初始化流程。下面, 我们看一下初始化流程的源码。
根据自动配置的原理,我们在 spring-boot-autoconfigure 包中的 META-INF/spring.factories配置文件中找到了针对 Servlet 自动配置的 EnableAutoConfiguration。
#自动配置
org. springframework . boot . autoconfigure . EnableAutoConfiguration=\
org. springframework. boot . autoconfigure . web. servlet . DispatcherServletAutoCon下面对 EnableAutoConfiguration 类中的自动配置项目进行逐步分析。
DispatcherServlet 自动配置
DispatcherServlet 自动配置位于
DispatcherServletAutoConfiguration 类