SpringBoot切换内嵌容器原理

废话不多说,是在最近面试被人问到的,直接上源码(以下是SpringBoot 2.x.x源码,SpringBoot 1.5.x版本略微有不同,不再赘述):

package org.springframework.boot.autoconfigure.web.embedded;

import io.undertow.Undertow;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.UpgradeProtocol;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.xnio.SslClientAuthMode;

@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties({ServerProperties.class})
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
    public EmbeddedWebServerFactoryCustomizerAutoConfiguration() {
    }

    @Configuration
    @ConditionalOnClass({Undertow.class, SslClientAuthMode.class}) //Undertow容器
    public static class UndertowWebServerFactoryCustomizerConfiguration {
        public UndertowWebServerFactoryCustomizerConfiguration() {
        }

        @Bean
        public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
            return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
        }
    }

    @Configuration
    @ConditionalOnClass({Server.class, Loader.class, WebAppContext.class}) //Jetty容器
    public static class JettyWebServerFactoryCustomizerConfiguration {
        public JettyWebServerFactoryCustomizerConfiguration() {
        }

        @Bean
        public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
            return new JettyWebServerFactoryCustomizer(environment, serverProperties);
        }
    }

    @Configuration
    @ConditionalOnClass({Tomcat.class, UpgradeProtocol.class}) //Tomcat容器
    public static class TomcatWebServerFactoryCustomizerConfiguration {
        public TomcatWebServerFactoryCustomizerConfiguration() {
        }

        @Bean
        public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) {
            return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
        }
    }
}

原理就是上面的EmbeddedWebServerFactoryCustomizerAutoConfiguration配置类已经把三种容器都配置好了,@ConditionalOnClass({Tomcat.class, UpgradeProtocol.class})切换为Tomcat容器,@ConditionalOnClass({Server.class, Loader.class, WebAppContext.class})切换为Jetty容器,@ConditionalOnClass({Undertow.class, SslClientAuthMode.class})切换为Undertow容器,这样就做到了根据依赖的Jar包自动切换。

SpringBoot把容器修改为Jetty

方法很简单,就是在pom.xml文件中,在引用的spring-boot-starter-web排除Tomcat的依赖包,然后再引入Jetty容器的依赖包,如下:

  
          
            org.springframework.boot  
            spring-boot-starter-web  
              
                  
                    org.springframework.boot  
                    spring-boot-starter-tomcat  
                  
              
          
  
          
          
          
            org.springframework.boot  
            spring-boot-starter-jetty  
          
          
            org.springframework.boot  
            spring-boot-starter-test  
            test  
          
  

你可能感兴趣的:(SpringBoot切换内嵌容器原理)