Spring Boot内嵌容器

使用 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 {

/**
* Nested configuration if Tomcat is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {

@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}

}

/**
* Nested configuration if Jetty is being used.
*/
@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();
}

}

/**
* Nested configuration if Undertow is being used.
*/
@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 容器。