一、spring boot内嵌web容器介绍
Spring Boot 支持以下内嵌的 Web 容器:
这些内嵌的 Web 容器都可以在 Spring Boot 应用中直接使用,无需额外的安装和配置。Spring Boot 会自动根据项目的依赖和配置来选择合适的 Web 容器,并进行相应的配置和启动。
你可以根据项目的需求和特点选择适合的 Web 容器。例如,如果对性能有较高要求,可以考虑使用 Undertow;如果需要与现有 Tomcat 环境集成,则可以选择 Tomcat。
二、如何切换spring boot内嵌web容器
以jetty为例,我们只需要将默认的tomcat依赖排除,并将jetty依赖引入,即可完成内嵌web容器的切换。
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
org.springframework.boot
spring-boot-starter-jetty
启动项目,我们可以看到,jetty确实启动了。
三、spring boot内嵌web容器启动原理
Spring Boot 内嵌 Web 容器的启动原理可以概括为以下几个步骤:
相关源码如下:
SpringApplication类createApplicationContext方法,根据当前web应用的类型选择匹配的应用上下文类型,这边会创建AnnotationConfigServletWebServerApplicationContext。
protected ConfigurableApplicationContext createApplicationContext() {
Class contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
AnnotationConfigServletWebServerApplicationContext类createWebServer方法,会创建我们配置的web容器。
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
这边使用了工厂模式,不同的web容器有自己的工厂。
这边我们以TomcatServletWebServerFactory为例,看下它的getWebServerFactory方法。
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
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);
return getTomcatWebServer(tomcat);
}
这边创建了tomcat容器并初始化,然后返回。