本文主要介绍
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>
本文详细解析了SpringBoot如何利用内置Tomcat启动原理,并指导读者如何在SpringBoot应用中切换默认的Servlet容器,从Tomcat切换到Jetty或Undertow。介绍了关键配置文件和依赖管理,助你理解并实现场景切换。
1502

被折叠的 条评论
为什么被折叠?



