DW做网站入门步骤教学/聊石家庄seo

作者:陌北有棵树,Java人,架构师社区合伙人!
【一】总述
SpringBoot的诞生,极大的简化了Spring框架的使用过程,提升了开发效率,可以把它理解为一个整合包,使用了SpringBoot,就可以不用自己去进行繁琐的配置,通过几个简单的注解,就可以构建一个基于REST的服务。同时,SpringBoot的快速构建部署的特性,为当下大热的微服务落地提供了极大的便利,可以说是构建微服务的理想框架。
归纳来说SpringBoot的特性有如下几点:
- 自动配置
- 内置tomcat、jetty、undertow 三大web容器
- 将Web应用打成jar包启动
那么SpringBoot是怎样做到上述三个特性的呢?是我接下来的研究方向,本篇主要研究的是后两个特点,如何内嵌了Web容易,将应用打成jar包,怎么还能像Web程序一样运行。
本文是笔者患难与共的好兄弟Dewey Ding及笔者Debug了若干天的成果,谨以此篇留作纪念。
【二】问题引出和总体思路
- 按照常规的Web容器的启动方式,明显是无法和SpringBoot这种jar包的运行方式兼容的,那么他们之间是如何做到无缝衔接的合作呢?
- 最终运行的依然是SpringMVC框架,那么SpringBoot又是如何做到在内置了Tomcat的同时,又和SpringMVC无缝衔接的呢?
- 综上所述,整个系列需要研究的技术点如下(本文并未完全覆盖):
- SpringBoot启动Tomcat
- SpringMVC初始化DispatcherServlet
- Tomcat的两种启动方式
- Tomcat在SpringBoot中如何拿到配置
【三】SpringBoot启动过程具体分析
在SpringBoot中,一个Web应用从启动到接收请求,我粗略将它分为四步:
- SpringBoot初始化
- 初始化SpringApplication:包括环境变量、资源、构造器、监听器
- 开始启动:启动监听(listeners)、加载配置(environment)、创建上下文(applicationContext)
- 自动化配置:这个部分等到后面单独研究
- Tomcat初始化
- Tomcat接收请求
- SpringMVC初始化
这一部分的学习真可谓一波三折,每次Debug SpringApplication的run方法,都会迷失在茫茫的源码之中,看书和博客也都是云里雾里,所以这次决定换一种学法,先从宏观上了解都要做什么,至于具体细节,等到需要的时候再去分析。比如今天要了解的是和Tomcat启动相关的部分,那么就先只了解这个模块。
关于SpringBoot和Tomcat是如何合作的,在实际Debug之前,我们先抛出如下几个问题:
- SpringBoot有main()方法,可以直接打成jar包运行;SpringMVC没有main方法,所以无法自己启动,要依赖Tomcat,Tomcat本质是个容器,所以Tomcat中一定有main方法或者线程的start()方法来启动Spring程序
- /WEB-INF是Web应用需要的,SpringMVC配置了这个,是为了Tomcat读取,从而启动Web容器
- 项目要部署到webapp目录下,才能被Tomcat运行
- 那么问题来了,SpringBoot没有做这些配置,是怎么做到内置Tomcat容器,并让Tomcat启动的呢?
【SpringBoot和Tomcat的初始化】
我们先来看Tomcat的启动时在SpringBoot启动的哪一步?这里只列举比较关键的几步:
- SpringApplication的run方法
org.springframework.boot.SpringApplication#run(java.lang.String...)
- 刷新IOC容器(Bean的实例化)
org.springframework.boot.SpringApplication#refreshContext()org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh()
- 创建WebServer
- 在org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh调用了createWebServer
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer()private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { // 重点:这时初始化了dispatcherServlet ServletWebServerFactory factory = getWebServerFactory(); // 创建 this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { // 启动 getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context