从源码层面理解spring boot的默认web容器,以及他们是如何关联起来的。


自动配置类:ServletWebServerFactoryAutoConfiguration在spring-boot-autoconfigure-2.6.6.jar这个包中的spring.factories文件内,配置了大量的自动配置类,其中就包括自动配置tomcat的自动配置类:ServletWebServerFactoryAutoConfiguration

// full模式
@Configuration(proxyBeanMethods = false)
// 配置类解析顺序
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
// 条件注解:表示项目依赖中要有ServletRequest类(server api)
@ConditionalOnClass(ServletRequest.class)
// 表示项目应用类型得是SpringMVC(在启动过程中获取的SpringBoot应用类型)
@ConditionalOnWebApplication(type = Type.SERVLET)
// 读取server下的配置文件
@EnableConfigurationProperties(ServerProperties.class)
// import具体的加载配置的类和具体web实现容器
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
......
}
@Configuration(proxyBeanMethods = false)
// tomcat内部的类,肯定都存在
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
// 程序员如果自定义了ServletWebServerFactory的Bean,那么这个Bean就不加载。
@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();
// orderedStream()调用时会去Spring容器中找到TomcatConnectorCustomizer类型的Bean,默认是没有的,程序员可以自己定义。这个Bean可以设置一些tomcat的配置,比如端口、协议...
// TomcatConnectorCustomizer:是用来配置Tomcat中的Connector组件的
factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
// TomcatContextCustomizer:是用来配置Tomcat中的Context组件的
factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
// TomcatProtocolHandlerCustomizer:是用来配置Tomcat中的ProtocolHandler组件的
factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}
}


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.setBaseDir(baseDir.getAbsolutePath());
for (LifecycleListener listener : this.serverLifecycleListeners) {
tomcat.getServer().addLifecycleListener(listener);
}
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);
// 启动tomcat,这个方法内部有this.tomcat.start();
return getTomcatWebServer(tomcat);
}
protected void onRefresh() {
// 模板方法,先调用它父类的,一般是空方法
super.onRefresh();
try {
// 创建web容器
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
这个方法会调用createWebServer()方法。
// 最核心的俩行代码
private void createWebServer() {
......
// 获取web容器,多个或者没有的时候报错
ServletWebServerFactory factory = getWebServerFactory();
// 调用这个容器的getWebServer方法,上面的启动tomcat的方法!
this.webServer = factory.getWebServer(getSelfInitializer());
......
}
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don"t consider the hierarchy
// 得到所有类型为ServletWebServerFactory的Bean。TomcatServletWebServerFactory、JettyServletWebServerFactory、UndertowServletWebServerFactory都是他得到子类!
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
// 不存在,报错
if (beanNames.length == 0) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.");
}
// 存在不止一个,报错!
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
// 返回唯一的一个web容器!
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// Bean工厂,一个Aware回调进行赋值
if (this.beanFactory == null) {
return;
}
// 注册webServerFactoryCustomizerBeanPostProcessor这个Bean。
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class,
WebServerFactoryCustomizerBeanPostProcessor::new);
// 注册errorPageRegistrarBeanPostProcessor
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class, ErrorPageRegistrarBeanPostProcessor::new);
}
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
// 找到WebServerFactoryCustomizer的Bean
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
// 标记日志用的类
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
// 调用customize方法,传入webServerFactory
.invoke((customizer) -> customizer.customize(webServerFactory));
}
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(this.serverProperties::getPort).to(factory::setPort);
map.from(this.serverProperties::getAddress).to(factory::setAddress);
map.from(this.serverProperties.getServlet()::getContextPath).to(factory::setContextPath);
map.from(this.serverProperties.getServlet()::getApplicationDisplayName).to(factory::setDisplayName);
map.from(this.serverProperties.getServlet()::isRegisterDefaultServlet).to(factory::setRegisterDefaultServlet);
map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession);
map.from(this.serverProperties::getSsl).to(factory::setSsl);
map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp);
map.from(this.serverProperties::getCompression).to(factory::setCompression);
map.from(this.serverProperties::getHttp2).to(factory::setHttp2);
map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);
map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters);
map.from(this.serverProperties.getShutdown()).to(factory::setShutdown);
for (WebListenerRegistrar registrar : this.webListenerRegistrars) {
registrar.register(factory);
}
if (!CollectionUtils.isEmpty(this.cookieSameSiteSuppliers)) {
factory.setCookieSameSiteSuppliers(this.cookieSameSiteSuppliers);
}
}
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties, ObjectProvider<WebListenerRegistrar> webListenerRegistrars, ObjectProvider<CookieSameSiteSupplier> cookieSameSiteSuppliers) {
return new ServletWebServerFactoryCustomizer(serverProperties,webListenerRegistrars.orderedStream().collect(Collectors.toList()),cookieSameSiteSuppliers.orderedStream().collect(Collectors.toList()));
}
到此这篇关于Spring boot整合tomcat底层原理的文章就介绍到这了,更多相关Spring boot整合tomcat内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!