加入收藏 | 设为首页 | 会员中心 | 我要投稿 甘南站长网 (https://www.0941zz.com/)- 科技、行业物联网、开发、云计算、云管理!
当前位置: 首页 > 运营中心 > Tomcat > 正文

Spring boot整合tomcat底层原理解析

发布时间:2023-02-20 09:59:06 所属栏目:Tomcat 来源:互联网
导读:从源码层面理解spring boot的默认web容器,以及他们是如何关联起来的。 源码基于spring boot2.6.6 项目的pom.xml中存在spring-boot-starter-web的时候,在项目启动时候就会自动启动一个Tomcat。 自动配置类ServletWebServerFactoryAutoConfiguration找到系统
  从源码层面理解spring boot的默认web容器,以及他们是如何关联起来的。
 
  源码基于spring boot2.6.6
  项目的pom.xml中存在spring-boot-starter-web的时候,在项目启动时候就会自动启动一个Tomcat。
  自动配置类ServletWebServerFactoryAutoConfiguration找到系统中的所有web容器。我们以tomcat为主。
  构建TomcatServletWebServerFactory的bean。
  SpringBoot的启动过程中,会调用核心的refresh方法,内部会执行onRefresh()方法,onRefresh()方法是一个模板方法,他会执行会执行子类ServletWebServerApplicationContext的onRefresh()方法。
  onRefresh()方法中调用getWebServer启动web容器。
 
  spring-boot-starter-web内部有什么?
  在spring-boot-starter-web这个starter中,其实内部间接的引入了spring-boot-starter-tomcat这个starter,这个spring-boot-starter-tomcat又引入了tomcat-embed-core依赖,所以只要我们项目中依赖了spring-boot-starter-web就相当于依赖了Tomcat。
 
 
  自动配置类:ServletWebServerFactoryAutoConfiguration在spring-boot-autoconfigure-2.6.6.jar这个包中的spring.factories文件内,配置了大量的自动配置类,其中就包括自动配置tomcat的自动配置类:ServletWebServerFactoryAutoConfiguration
 
 
  自动配置类的代码如下
 
  // full模式
  @Configuration(proxyBeanMethods = false)
  
  // 配置类解析顺序
  @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
  
  // 条件注解:表示项目依赖中要有ServletRequest类(server api)
  @ConditionalOnClass(ServletRequest.class)
  // 表示项目应用类型得是SpringMVC(在启动过程中获取的SpringBoot应用类型)
  @ConditionalOnWebApplication(type = Type.SERVLET)
  
  // 读取server下的配置文件
  @EnableConfigurationProperties(ServerProperties.class)
  
  // import具体的加载配置的类和具体web实现容器
  @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
          ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
          ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
          ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
  public class ServletWebServerFactoryAutoConfiguration {
      ......
  }
  ServletRequest是存在于tomcat-embed-core-9.0.60.jar中的的一个类,所以@ConditionalOnClass(ServletRequest.clas s)会满足。
  spring-boot-starter-web中,间接的引入了spring-web、spring-webmvc等依赖,所以@ConditionalOnWebApplication(type = Type.SERVLET)条件满足。
  上面的俩个条件都满足,所以spring回去解析这个配置类,在解析过程中会发现他import了三个类!我们重点关注EmbeddedTomcat。其他俩个的内部条件注解不满足!
  
  @Cnfiguration(proxyBeanMethods = false)
  // tomcat内部的类,肯定都存在
  @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
  
  // 程序员如果自定义了ServletWebServerFactory的Bean,那么这个Bean就不加载。
  @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();
              // orderedStream()调用时会去Spring容器中找到TomcatConnectorCustomizer类型的Bean,默认是没有的,程序员可以自己定义。这个Bean可以设置一些tomcat的配置,比如端口、协议...
              // TomcatConnectorCustomizer:是用来配置Tomcat中的Connector组件的
              factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
              // TomcatContextCustomizer:是用来配置Tomcat中的Context组件的
              factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
              // TomcatProtocolHandlerCustomizer:是用来配置Tomcat中的ProtocolHandler组件的
              factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
              return factory;
          }
      }
  }
  对于另外的EmbeddedJetty和EmbeddedUndertow,逻辑类似,都是判断项目依赖中是否有Jetty和Undertow的依赖,如果有,那么对应在Spring容器中就会存在JettyServletWebServerFactory类型的Bean、或者存在UndertowServletWebServerFactory类型的Bean。
 
  TomcatServletWebServerFactory的作用:获取WebServer对象
  TomcatServletWebServerFactory他实现了ServletWebServerFactory这个接口。
  ServletWebServerFactory接口内部只有一个方法是获取WebServer对象。
 
 
  WebServer拥有启动、停止、获取端口等方法,就会发现WebServer其实指的就是Tomcat、Jetty、Undertow。
 
 
  而TomcatServletWebServerFactory就是用来生成Tomcat所对应的WebServer对象,具体一点就是TomcatWebServer对象,并且在生成TomcatWebServer对象时会把Tomcat给启动起来。
  在源码中,调用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.setBaseDir(baseDir.getAbsolutePath());
      for (LifecycleListener listener : this.serverLifecycleListeners) {
          tomcat.getServer().addLifecycleListener(listener);
      }
      Connector connector = new Connector(this.protocol);
      connector.setThrowOnFailure(true);
      tomcat.getService().addConnector(connector);
      customizeConnector(connector);
      tomcat.setConnector(connector);
      tomcat.getHost().setAutoDeploy(false);
      configureEngine(tomcat.getEngine());
      for (Connector additionalConnector : this.additionalTomcatConnectors) {
          tomcat.getService().addConnector(additionalConnector);
      }
      prepareContext(tomcat.getHost(), initializers);
  
      // 启动tomcat,这个方法内部有this.tomcat.start();
      return getTomcatWebServer(tomcat);

(编辑:甘南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读