使用 Spring Boot 工程时默认 web 容器是 Tomcat,但是可以根据需要进行修改,例如使用 Jetty 或者 Undertow。只需要排除spring-boot-starter-web包中的spring-boot-starter-tomcat,然后添加其它的容器即可,例如spring-boot-starter-jetty。
不用修改任何代码即可完成容器的切换,那么 Spring Boot 到底是如何实现的呢?关键在EmbeddedServletContainerAutoConfiguration类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplication @Import(BeanPostProcessorsRegistrar.class) public class EmbeddedServletContainerAutoConfiguration { @Configuration @ConditionalOnClass({ Servlet.class, Tomcat.class }) @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedTomcat { @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory () { return new TomcatEmbeddedServletContainerFactory (); } } @Configuration @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class }) @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedJetty { @Bean public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory () { return new JettyEmbeddedServletContainerFactory (); } } @Configuration @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class }) @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedUndertow { @Bean public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory () { return new UndertowEmbeddedServletContainerFactory (); } } }
核心注解说明
@ConditionalOnClass:表示对应的类在 classpath 目录下存在时,才会实例化一个 Bean;
@ConditionalOnMisssingClass:表示对应的类在 classpath 目录下找不到,才会实例化一个 Bean。
Spring Boot 根据在 classpath 下扫描到的容器类的类型决定使用哪个 web 容器。例如:当引入了 Undertow 容器的 jar 包,classpath 目录下一定会有 Undertow 相关的 class,满足@ConditionalOnClass限制条件,此时 Spring Boot 将使用UndertowEmbeddedServletContainerFactory来生成 Undertow 容器。