精华内容
下载资源
问答
  • springboot内嵌tomcat原理
    万次阅读
    2020-10-06 21:04:49

    一、序言

    使用SpringBoot经常会使用内嵌的tomcat做为项目的启动容器,本文将从源码的角度出发,剖析SpringBoot内嵌Tomcat的实现原理,讨论Tomcat何时创建、何时启动以及怎么启动。

    二、引入Tomcat组件

    导入依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web
    更多相关内容
  • 对于SpringBoot应用来说,不管应用程序是属于何种类型,都是一个Main方法走遍天下,而且对于web应用,只需要引入spring-boot-starter-web中这个依赖,应用程序就好像直接给我们来了个tomcat一样,其实,这里并不是...

    1.嵌入式Tomcat

    懂得SpringBoot的童鞋应该很清楚,对于SpringBoot应用来说,不管应用程序是属于何种类型,都是一个Main方法走遍天下,而且对于web应用,只需要引入spring-boot-starter-web中这个依赖,应用程序就好像直接给我们来了个tomcat一样,其实,这里并不是SpringBoot团队里面有什么骚操作,而是Tomcat本身提供的外部接口,使其它应用程序能够非常方便的将Tomca嵌入t到自身的应用来。
    对于嵌入式Tomcat,其实也非常简单,就是调用Tomcat提供的外部类org.apache.catalina.startup.Tomcat而已,下面,我们通过代码来简单描述一下,如何在我们自身的程序嵌入Tomcat。
    maven依赖

      <dependency>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
      </dependency>
    

    简单的一个servlet

    public class DemoServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        @Override
        public void doGet(HttpServletRequest request,
                          HttpServletResponse response)
                throws IOException, ServletException {
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
    
            out.println("<!DOCTYPE html><html>");
            out.println("<head>");
            out.println("<meta charset="UTF-8" />");
            out.println("<title></title>");
            out.println("</head>");
            out.println("<body bgcolor="white">");
            out.println("<h1> 嵌入式tomcat</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }
    

    EmbeddedTomcatServer 嵌入式Tomat入口:

    public class EmbeddedTomcatServer {
        public static void main(String[] args) throws Exception {
            //把目录的绝对的路径获取到
            String classpath = System.getProperty("user.dir");
            System.out.println(classpath);
            //new一个Tomcat
            Tomcat tomcat = new Tomcat();
    
            //插件是6或者6以前的
            //Embbedded
            //设置Tomcat的端口
            //tomcat.setPort(9090);
            Connector connector = tomcat.getConnector();
            connector.setPort(9091);
            //设置Host
            Host host = tomcat.getHost();
            //我们会根据xml配置文件来
            host.setName("localhost");
            host.setAppBase("webapps");
            //前面的那个步骤只是把Tomcat起起来了,但是没啥东西
            //要把class加载进来,把启动的工程加入进来了
            Context context = tomcat.addContext(host, "/", classpath);
    
            if (context instanceof StandardContext) {
                StandardContext standardContext = (StandardContext) context;
                standardContext.setDefaultContextXml("E:\apache-tomcat-8.5.51\conf\web.xml");
                //我们要把Servlet设置进去
                Wrapper wrapper = tomcat.addServlet("/", "DemoServlet", new DemoServlet());
                wrapper.addMapping("/embeddedTomcat");
            }
            //Tomcat跑起来
            tomcat.start();
            //强制Tomcat server等待,避免main线程执行结束后关闭
            tomcat.getServer().await();
        }
    
    }
    

    运行结果:
    在这里插入图片描述
    EmbeddedTomcatServer类作为程序的入口,代码逻辑其实就是通过tomcat提供的外部接口类在配置server.xml这个文件;要了解这个类的每个配置步骤,可能需要对tomcat相关组件有一定的理解,如下所示,对于每个组件的作用,博主画了一个图进行简单的介绍
    在这里插入图片描述
    对于Tomcat源码的构建,有兴趣的童鞋可参考这篇文章:https://www.jb51.net/article/95120.htm

    2. Spring内嵌Tomcat原理剖析

    其实SpringBoot嵌入Tomcat等其它web容器,关键是在类ServletWebServerApplicationContext的onRefresh方法,如下为该方法的代码定义:
    在这里插入图片描述
    继续进入createWebServer()方法
    在这里插入图片描述
    进入TomcatServletWebServerFactory#getWebServer()方法。如下所示
    在这里插入图片描述
    通过上面流程分析,可以发现,SpringBoot嵌入Tomcat也是通过调用Tomcat提供的外部类org.apache.catalina.startup.Tomcat进行开发的。

    展开全文
  • Spring Boot默认支持Tomcat,Jetty,和Undertow作为底层容器。而Spring Boot默认使用Tomcat,一旦引入spring-boot-starter-web模块,就默认使用Tomcat容器。 在启动springboot的时候可谓是相当简单,只需要执行以下...

    Spring Boot默认支持Tomcat,Jetty,和Undertow作为底层容器。而Spring Boot默认使用Tomcat,一旦引入spring-boot-starter-web模块,就默认使用Tomcat容器。

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    在启动springboot的时候可谓是相当简单,只需要执行以下代码:

    @SpringBootApplication
    public class SpringBootMyTestApplication {
       public static void main(String[] args) {
          SpringApplication.run(SpringBootMyTestApplication.class, args);
       }
    }
    

    那些看似简单的事物,其实并不简单。我们之所以觉得他简单,是因为复杂性都被隐藏了。通过上诉代码,大概率可以提出以下几个疑问

    1. SpringBoot是如何启动内置tomcat的 - 文章的重点
    2. SpringBoot为什么可以响应请求,他是如何配置的SpringMVC
      这次的重点是先分享SpringBoot是如何启动内置的Tomcat的

    1.内嵌Tomcat自动配置原理

    1.1 Tomcat服务自动配置类

    在SpringBoot的启动过程中会自动加载各个模块下的META-INF/spring.factories文件中定义的自动配置类,Tomcat的服务的加载也是如此,所以首先要找到加载的自动配置,如下图所示:
    在这里插入图片描述
    找到这个配置类进去看一下实现的内容:
    在这里插入图片描述
    可以看到里面也通过@Import注解将EmbeddedTomcat、EmbeddedJetty、EmbeddedUndertow等嵌入式容器类加载进来了,springboot默认是启动嵌入式tomcat容器,如果要改变启动jetty或者undertow容器,需在pom文件中去设置。
    这里默认实现的是Tomcat容器,那么看一下EmbeddedTomcat:
    在这里插入图片描述
    进入TomcatServletWebServerFactory类,里面的getWebServer()是关键方法,如图:
    在这里插入图片描述
    继续进入getTomcatWebServer()等方法,一直往下跟到tomcat初始化方法,调用tomcat.start()方法,tomcat就正式开启运行,见图:
    在这里插入图片描述
    走到这里tomcat在springboot中的配置以及最终启动的流程就走完了。

    1.2 SpringBoot启动Tomcat

    在SpringBoot启动过程中有一个很重要的步骤:

    // 刷新应用上下文
    refreshContext(context);
    

    内置tomcat的启动就是在这个方法中进行调用的,点击实现的逻辑,最终进到了Spring的源码中:
    在这里插入图片描述
    上面的这个onRefresh()方法就是关键点,点击进行查看源码,onRefresh()会调用到ServletWebServerApplicationContext中的createWebServer(),

    private void createWebServer() {
       WebServer webServer = this.webServer;
       ServletContext servletContext = getServletContext();
       if (webServer == null && servletContext == null) {
          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", ex);
          }
       }
       initPropertySources();
    }
    

    createWebServer()就是启动web服务,但是还没有真正启动Tomcat,既然webServer是通过ServletWebServerFactory来获取的,先来看一下getWebServerFactory()方法的实现:

    protected ServletWebServerFactory getWebServerFactory() {
       // Use bean names so that we don't consider the hierarchy
       String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
       if (beanNames.length == 0) {
          throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
                + "ServletWebServerFactory bean.");
       }
       if (beanNames.length > 1) {
          throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
                + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
       }
       return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }
    

    看最后一步的返回,因为这里使用的是tomcat容器,所以最终返回的就是一个TomcatServletWebServerFactory实例,最终就调用了TomcatServletWebServerFactory类的getWebServer()方法,那么也就实现了tomcat服务的启动。
    debug验证一下上述的流程:
    在这里插入图片描述

    2.小结

    附上源码流程图:
    在这里插入图片描述

    展开全文
  • 一、序言使用SpringBoot经常会使用内嵌的tomcat做为项目的启动容器,本文将从源码的角度出发,剖析SpringBoot内嵌Tomcat的实现原理,讨论Tomcat何时创建、何时启动以及怎么启动。二、引入Tomcat组件导入依赖:org....

    一、序言

    使用SpringBoot经常会使用内嵌的tomcat做为项目的启动容器,本文将从源码的角度出发,剖析SpringBoot内嵌Tomcat的实现原理,讨论Tomcat何时创建、何时启动以及怎么启动。

    二、引入Tomcat组件

    导入依赖:

    org.springframework.boot

    spring-boot-starter-web

    项目启动:

    @SpringBootApplication

    public class Application {

    public static void main(String[] args) {

    SpringApplication.run(Application.class, args);

    }

    }

    以上是一段常见的SpringBoot项目依赖和启动的代码。引入spring-boot-starter-web同时会默认引入spring-boot-starter-tomcat,即Tomcat启动的相关环境。而对于项目启动代码,@SpringBootApplication主要实现Spring组件扫描和自动配置。该注解是复合注解,其中@EnableAutoConfiguration本身也是一个复合注解,包含以下内容:

    @AutoConfigurationPackage

    @Import(AutoConfigurationImportSelector.class)

    public @interface EnableAutoConfiguration {

    }

    这两个注解比较关键。@AutoConfigurationPackage主要实现自动配置包,会扫描@SpringbootApplication标注的类所在包名及其子包,将创建的组件添加到容器中;而@Import则是导入了AutoConfigurationImportSelector.class,实现查找classpath上所有jar包中的META-INF/spring.factories,找出其中的自动配置类并导入到容器中,其中Web容器所对应的自动配置类为ServletWebServerFactoryAutoConfiguration。

    9081e90e7556f34c7966a300f3177b88.png

    ServletWebServerFactoryAutoConfiguration中支持好几种web容器,比如Tomcat、Jetty和Undertow。

    30516df339ba098f47f27d498d67c237.png

    而EmbeddedTomcat则是Tomcat组件相关的类,本身是一个FactoryBean,用来实例化TomcatServletWebServerFactory。此时TomcatServletWebServerFactory中就包含了创建和启动Tomcat的方法getWebServer()。

    4e55504add50614c83987687ee2ab928.png

    三、Tomcat组件启动

    SpringBoot是在项目启动的时候才同时启动Tomcat的,很显然getWebServer()是在项目启动的过程中调用的。跟踪SpringApplication的run(),其中存在refreshContext(context),此时主要完成容器的刷新。

    f4c9f76ff0b34b92d9f9ef6d02f42703.png

    容器刷新跟踪到最后是AbstractApplicationContext中的onRefresh(),显然这是一个钩子函数,应用了模板方法,查看所有的实现方法,其中有一个ServletWebServerApplicationContext,则是当前Web容器的实现。

    ecb0a4b3b94ed09bb4b959bb80b9682a.png

    而ServletWebServerApplicationContext中主要是去获得ServletWebServerFactory对象,同时调用getWebServer创建WebServer对象。

    5eeb6e9162c1e8545f0d28c6644d7a27.png

    此时,主要处理的是Tomcat容器对象的创建、环境配置和启动。

    18db92cb9ee80c4e02e0044203261768.png

    ca1e877cba538817a4b15036be00d2bb.png

    四、总结

    到这里,基本就走完了内嵌Tomcat创建启动的整个流程。其实核心主要还是依赖于SpringBoot的自动配置。项目启动的过程中,扫描classpath下的META-INF/spring.factories,实例化工厂对象TomcatServletWebServerFactory,在调用run()方法的时候完成Tomcat对象的创建,环境设置和启动,从而实现Tomcat容器的自动化处理。

    到此这篇关于浅谈SpringBoot内嵌Tomcat的实现原理解析的文章就介绍到这了,更多相关SpringBoot内嵌Tomcat内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    本文标题: 浅谈SpringBoot内嵌Tomcat的实现原理解析

    本文地址: http://www.cppcns.com/ruanjian/java/370370.html

    展开全文
  • springboot内嵌tomcat原理

    2020-07-31 21:21:51
    主要的依赖标志就是有 spring-boot-starter-web 这个 starter ,spring-boot-starter-web 模块在 spring boot 中其实并没有代码存在,只是在 pom.xml 中携带了一些依赖,包括 web、webmvc、tomcat 等 <...
  • SpringBoot嵌入Tomcat原理 内嵌Tomcat启动原理 首先,来到启动SpringBoot项目的地方,也就是朱配置类. @SpringBootApplication public class InakiApplication { public static void main(String[] args) { ...
  • SpringBootTomcat 的集成流程分析
  • 一文搞懂SpringBoot内嵌Tomcat:

    千次阅读 2022-02-25 16:37:38
    一文帮助你搞懂SpringBoot内嵌Tomcat。冲击吧,少年。
  • AutoConfiguration有一个ServletWebServerFactoryAutoConfiguration会被加载进来(细节在我的SpringBoot自动装配中有) 所以才会获得tomcat对应的工厂。 进入getWebServer(),有多种实现 细节的创建 ...
  • Springboot
  • 第八章 内嵌Tomcat原理 文章目录SpringBoot 源码深度解析前言内嵌Tomcat自动配置原理SpringBoot启动内置tomcat流程 前言 内嵌Tomcat原理 Spring Boot默认支持Tomcat,Jetty,和Undertow作为底层容器。 而Spring...
  • Spring Boot内嵌Tomcat原理

    千次阅读 2022-03-17 19:33:05
    基于Spring Boot 2.x,详细进行了Spring Boot项目的启动源码中的内嵌Tomcat原理分析
  • 不得不说SpringBoot的开发者是在为大众程序猿谋福利,把大家都惯成了懒汉,xml不配置了,连tomcat也懒的配置了,典型的一键启动系统,那么tomcatspringboot是怎么启动的呢? 内置tomcat 开发阶段对我们来说使用...
  • 这篇文章主要从源码的角度出发,解析 Spring Boot 内嵌 Tomcat 的实现原理,讨论 Tomcat 何时创建、启动以及是怎样启动的。 下面跟随源码一步步找到如何启动内置的 tomcat。 首先贴出启动类: @SpringBoot...
  • SpringBoot中内置Tomcat启动原理 1.Tomcat容器对象注入 需要向Spring容器注入的对象有: SpringApplication:SpringBoot启动类,在这个类的构造器中,决定了判断项目是WebApplicationType【REACTIVE,NONE,...
  • Spring Boot默认支持Tomcat,Jetty,和Undertow作为底层容器。 而Spring Boot默认使用Tomcat,一旦引入spring-boot-starter-web模块,就默认使用Tomcat容器。 <dependency> <groupId>org.spring...
  • 文章目录SpringBoot 是如何通过jar包启动的java -jar做了什么疑惑出现Jar包的打包插件及核心方法jar包目录结构... 启动使用外部Servlet容器外部Servlet容器启动SpringBoot应用原理什么是SPI SpringBoot 是如何通过ja
  • SpringBoot启动内嵌容器,启动时自动加载tomcat原理,tomcat内嵌集成实现
  • 内嵌Tomcat流程解析 一.@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class BeanPostProcessorsRegistrar是一个静态内部类,继承以及实现关系如下图: 简而言之,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,863
精华内容 1,545
热门标签
关键字:

springboot内嵌tomcat原理

spring 订阅