Spring Boot内置Tomcat启动源码分析

本文主要介绍

1. Spring Boot内置Tomcat启动原理;

2. 切换Spring Boot默认Servlet容器;

1. Spring Boot内置Tomcat启动原理;

 

 1. Spring Boot默认支持Tomcat,Jetty,和Undertow作为底层容器;在无特殊配置时,底层容器默认为Tomcat(spring-boot-starter-web中默认依赖Tomcat, 具体见下文)

在spring-boot-autoconfigure下的META-INF/spring.factories中key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration

配置的自动装配类信息包含org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration 

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
      ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
      ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
      ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {

  ...................

(默认支持Tomcat,Jetty,和Undertow作为底层容器) 

@Configuration(proxyBeanMethods = false)
class ServletWebServerFactoryConfiguration {

   @Configuration(proxyBeanMethods = false)
   @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
   @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
   static class EmbeddedTomcat {
      @Bean
      TomcatServletWebServerFactory tomcatServletWebServerFactory(
            ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
            ObjectProvider<TomcatContextCustomizer> contextCustomizers,
            ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
         TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
         factory.getTomcatConnectorCustomizers()
               .addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
         factory.getTomcatContextCustomizers()
               .addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
         factory.getTomcatProtocolHandlerCustomizers()
               .addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
         return factory;
      }

   }

   /**
    * Nested configuration if Jetty is being used.
    */
   @Configuration(proxyBeanMethods = false)
   @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
   @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
   static class EmbeddedJetty {

      @Bean
      JettyServletWebServerFactory JettyServletWebServerFactory(
            ObjectProvider<JettyServerCustomizer> serverCustomizers) {
         JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
         factory.getServerCustomizers().addAll(serverCustomizers.orderedStream().collect(Collectors.toList()));
         return factory;
      }

   }

   /**
    * Nested configuration if Undertow is being used.
    */
   @Configuration(proxyBeanMethods = false)
   @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
   @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
   static class EmbeddedUndertow {

      @Bean
      UndertowServletWebServerFactory undertowServletWebServerFactory(
            ObjectProvider<UndertowDeploymentInfoCustomizer> deploymentInfoCustomizers,
            ObjectProvider<UndertowBuilderCustomizer> builderCustomizers) {
         UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
         factory.getDeploymentInfoCustomizers()
               .addAll(deploymentInfoCustomizers.orderedStream().collect(Collectors.toList()));
         factory.getBuilderCustomizers().addAll(builderCustomizers.orderedStream().collect(Collectors.toList()));
         return factory;
      }

   }

}

默认情况下 EmbeddedTomcat 条件注解会生效会创建 TomcatServletWebServerFactory  的实例对象而 EmbeddedJetty 及 EmbeddedUndertow 的条件注解将不生效;

TomcatServletWebServerFactory 中存在getWebServer方法,此方法会创建及启动一个Tomcat

public WebServer getWebServer(ServletContextInitializer... initializers) {
   if (this.disableMBeanRegistry) {
      Registry.disableRegistry();
   }
   //实例化一个Tomcat
   Tomcat tomcat = new Tomcat();
   File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
   //设置Tomcat的工作临时目录
   tomcat.setBaseDir(baseDir.getAbsolutePath());
   //默认使用Http11NioProtocal实例化Connector
   Connector connector = new Connector(this.protocol);
   connector.setThrowOnFailure(true);
   //给Service添加Connector
   tomcat.getService().addConnector(connector);
   customizeConnector(connector);
   tomcat.setConnector(connector);
   //关闭热部署
   tomcat.getHost().setAutoDeploy(false);
   //配置Engine
   configureEngine(tomcat.getEngine());
   for (Connector additionalConnector : this.additionalTomcatConnectors) {
      tomcat.getService().addConnector(additionalConnector);
   }
   prepareContext(tomcat.getHost(), initializers);
   // 实例化TomcatWebServer时会将DispatcherServlet以及一些Filter添加到Tomcat中
   return getTomcatWebServer(tomcat);
}

getTomcatWebServer(tomcat) 方法最终会启动Tomcate 

this.tomcat.start(); 

2. 在Spring Boot 启动过程中,刷新上下文(refreshContext)时 会通过上下文对象ConfigurableApplicationContext调用Spring的核心方法refresh;

在AbstractApplicationContext.fresh中通过

A.invokeBeanFactoryPostProcessors(beanFactory)方法会加载在META-INF下spring.facories下key为 EnableAutoConfiguration全限定类名的值,并将类信息存入IOC容器;

B.onRefresh()方法调用TomcatServletWebServerFactory 的 getWebServer方法,创建及启动一个Tomcat;

2. 切换Spring Boot默认Servlet容器

1. SpringBoot默认Servlet容器为Tomcat

在spring-boot-starter-web依赖中

<artifactId>spring-boot-starter-web</artifactId>
<name>Spring Boot Web Starter</name>
<dependencies>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
      <exclusions>
         <exclusion>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-el</artifactId>
         </exclusion>
      </exclusions>
   </dependency>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
   </dependency>
</dependencies>

 2. 切换Spring Boot默认Servlet容器为Jetty

Spring Boot 官方提供了Servlet容器Starter方式:Spring Boot Starters

包含

spring-boot-starter-tomcat (默认)
spring-boot-starter-undertow
spring-boot-starter-jetty

切换Spring Boot默认Servlet容器,只需将默认的tomcat 移除,引入需要切换的容器的starter

 1.移除默认的Tomcat 依赖

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

2. 引入 jetty 依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值