日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Spring boot整合tomcat底層原理剖析

瀏覽:226日期:2023-03-19 16:51:50
目錄
  • 本文結論
  • spring-boot-starter-web內部有什么?
  • TomcatServletWebServerFactory的作用:獲取WebServer對象
  • spring boot啟動的時候啟動tomcat
  • 獲取tomcat的配置
  • ServletWebServerFactoryCustomizer這個Bean是哪里的?

從源碼層面理解spring boot的默認web容器,以及他們是如何關聯起來的。

本文結論

  • 源碼基于spring boot2.6.6
  • 項目的pom.xml中存在spring-boot-starter-web的時候,在項目啟動時候就會自動啟動一個Tomcat。
  • 自動配置類ServletWebServerFactoryAutoConfiguration找到系統中的所有web容器。我們以tomcat為主。
  • 構建TomcatServletWebServerFactory的bean。
  • SpringBoot的啟動過程中,會調用核心的refresh方法,內部會執行onRefresh()方法,onRefresh()方法是一個模板方法,他會執行會執行子類ServletWebServerApplicationContext的onRefresh()方法。
  • onRefresh()方法中調用getWebServer啟動web容器。

spring-boot-starter-web內部有什么?

  • 在spring-boot-starter-web這個starter中,其實內部間接的引入了spring-boot-starter-tomcat這個starter,這個spring-boot-starter-tomcat又引入了tomcat-embed-core依賴,所以只要我們項目中依賴了spring-boot-starter-web就相當于依賴了Tomcat。

自動配置類: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 {	......}
  • ServletRequest是存在于tomcat-embed-core-9.0.60.jar中的的一個類,所以@ConditionalOnClass(ServletRequest.clas s)會滿足。
  • spring-boot-starter-web中,間接的引入了spring-web、spring-webmvc等依賴,所以@ConditionalOnWebApplication(type = Type.SERVLET)條件滿足。
  • 上面的倆個條件都滿足,所以spring回去解析這個配置類,在解析過程中會發現他import了三個類!我們重點關注EmbeddedTomcat。其他倆個的內部條件注解不滿足!
@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;}    }}
  • 對于另外的EmbeddedJetty和EmbeddedUndertow,邏輯類似,都是判斷項目依賴中是否有Jetty和Undertow的依賴,如果有,那么對應在Spring容器中就會存在JettyServletWebServerFactory類型的Bean、或者存在UndertowServletWebServerFactory類型的Bean。

TomcatServletWebServerFactory的作用:獲取WebServer對象

  • TomcatServletWebServerFactory他實現了ServletWebServerFactory這個接口。
  • ServletWebServerFactory接口內部只有一個方法是獲取WebServer對象。

  • WebServer擁有啟動、停止、獲取端口等方法,就會發現WebServer其實指的就是Tomcat、Jetty、Undertow。

  • 而TomcatServletWebServerFactory就是用來生成Tomcat所對應的WebServer對象,具體一點就是TomcatWebServer對象,并且在生成TomcatWebServer對象時會把Tomcat給啟動起來。
  • 在源碼中,調用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.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);}

spring boot啟動的時候啟動tomcat

  • SpringBoot的啟動過程中,會調用核心的refresh方法,內部會執行onRefresh()方法,onRefresh()方法是一個模板方法,他會執行會執行子類ServletWebServerApplicationContext的onRefresh()方法。
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());    ......}
  • getWebServerFactory控制項目組有且只能有一個web容器!
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);}

獲取tomcat的配置

  • 自動配置類ServletWebServerFactoryAutoConfiguration上除了import三個web容器,還import了BeanPostProcessorsRegistrar。
  • BeanPostProcessorsRegistrar實現了ImportBeanDefinitionRegistrar,所以他會在spring啟動的時候調用registerBeanDefinitions方法。
  • registerBeanDefinitions會注冊一個Bean:webServerFactoryCustomizerBeanPostProcessor。
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);}
  • webServerFactoryCustomizerBeanPostProcessor實現了BeanPostProcessor,所以他會在啟動的時候調用postProcessBeforeInitialization方法。
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {    // 找到WebServerFactoryCustomizer的Bean    LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)// 標記日志用的類.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)// 調用customize方法,傳入webServerFactory.invoke((customizer) -> customizer.customize(webServerFactory));}
  • postProcessBeforeInitialization中會調用WebServerFactoryCustomizer類customize方法,在系統中的唯一實現:ServletWebServerFactoryCustomizer的customize方法。
  • customize把配置中的內容設置到ConfigurableServletWebServerFactory對象中。他的實現TomcatServletWebServerFactory在啟動的時候就會有值!
@Overridepublic 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);    }}

ServletWebServerFactoryCustomizer這個Bean是哪里的?

  • 在我們自動配置類ServletWebServerFactoryAutoConfiguration中定義。
@Beanpublic 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內容請搜索以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持!

標簽: Tomcat
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日本色综合中文字幕| 国产精品av一区二区| 久久人人97超碰国产公开结果| 91精品国产自产观看在线| 亚洲视频二区| 亚洲中午字幕| 久久av在线| 日韩欧美在线精品| 91成人在线精品视频| 91九色综合| 精品国产黄a∨片高清在线| 国产剧情一区二区在线观看| 欧美精品国产白浆久久久久| 国产精品v亚洲精品v日韩精品| 91大神在线观看线路一区| 99视频一区| 日韩精品久久理论片| 国产精品中文| 美女一区网站| 视频一区欧美日韩| 欧美日一区二区三区在线观看国产免 | 国产精品毛片| 亚洲开心激情| 欧美精品导航| 麻豆一区二区三区| 黄在线观看免费网站ktv| 中日韩男男gay无套| 久久国产日韩欧美精品| 国产精品片aa在线观看| 国产一区国产二区国产三区| 欧美精品自拍| 国产欧美另类| 国产日韩电影| 日韩免费精品| 成人国产精选| 蜜桃av一区二区三区电影| 亚洲综合图色| 成人在线免费观看网站| 午夜在线精品| 久久国产66| 日韩高清欧美| 久久xxxx| 亚洲三级欧美| 国产欧美久久一区二区三区| 日韩综合精品| 欧美在线日韩| 亚洲韩日在线| 日韩av自拍| 亚洲三区欧美一区国产二区| 久久精品国产www456c0m| 日本麻豆一区二区三区视频| 亚洲免费观看| 色综合五月天| 免费观看日韩电影| 少妇久久久久| 国产亚洲综合精品| 最近高清中文在线字幕在线观看1| 国产农村妇女精品一区二区| 美日韩一区二区三区| 欧美午夜不卡影院在线观看完整版免费| 欧美日韩亚洲一区三区| 红桃视频欧美| 国产精品av一区二区| 麻豆国产精品视频| 国产毛片一区二区三区| 蜜桃av一区| 亚洲天堂黄色| 精品欧美日韩精品| 美国三级日本三级久久99| 91精品国产乱码久久久久久久| 国产66精品| 国产精品乱战久久久| 美国三级日本三级久久99| 日韩午夜在线| 亚洲精品福利| 日韩精品一区二区三区中文在线| 亚洲综合婷婷| 国产精品视频一区二区三区四蜜臂 | 国产亚洲久久| 日韩精品成人| 国产精品日韩精品中文字幕| 你懂的国产精品永久在线| 久久av偷拍| 91看片一区| 国产精品毛片| 免费在线日韩av| 在线一区视频观看| 免播放器亚洲| 国产精品一区二区中文字幕| 日韩av自拍| 不卡在线一区二区| 婷婷精品在线| 水蜜桃久久夜色精品一区| 九一国产精品| 日韩**一区毛片| 成人三级高清视频在线看| 欧美日韩少妇| 国产精品jk白丝蜜臀av小说| 国产+成+人+亚洲欧洲在线| 亚洲精品中文字幕乱码| 日韩欧美久久| 中文字幕系列一区| 91精品国产自产观看在线| 日产精品一区| 一区二区三区国产在线| 久久国内精品视频| 亚洲一区二区免费看| 国产精品一区二区精品视频观看 | 欧美日韩色图| 18国产精品| 激情综合网址| 精品国产亚洲一区二区三区| 另类激情亚洲| 成人看片网站| 九九久久国产| 亚洲伊人影院| 91超碰国产精品| 国产精品成久久久久| 日精品一区二区三区| 欧美+亚洲+精品+三区| 四季av一区二区凹凸精品| 日本国产一区| 亚洲一区日韩在线| 亚洲精品88| 高潮一区二区| 精品国产一区二| 欧美日韩夜夜| 亚洲aⅴ网站| 午夜宅男久久久| 亚洲综合三区| 久久亚洲精品伦理| 天堂√8在线中文| 亚洲欧美日韩精品一区二区| 中文在线不卡| 日本亚洲三级在线| 国产乱子精品一区二区在线观看| 欧美一级一区| 国精品产品一区| 欧美+日本+国产+在线a∨观看| av不卡在线看| 欧美日韩亚洲一区| 欧美一区成人| 日韩久久一区二区三区| 午夜精品免费| 欧美日韩国产欧| 国产精品美女| 国产精品magnet| 午夜精品成人av| 亚洲少妇诱惑| 不卡福利视频| 91欧美精品| 欧美gv在线| 777久久精品| 激情丁香综合| 成人美女视频| 久久精品国产精品亚洲毛片| 五月综合激情| 国产成人免费| 视频一区中文字幕精品| 国产色99精品9i| 国产美女精品视频免费播放软件| 国产剧情在线观看一区| 久久精品一区二区不卡| 国产欧美日韩一区二区三区四区| 999久久久国产精品| 久久只有精品| 欧美精品99| 国产精品亚洲人成在99www| 国产99亚洲| av免费不卡国产观看| 国产精品毛片视频| 91成人小视频| 蜜臀a∨国产成人精品| 精品久久福利| 亚洲精品成人一区| 国产精品观看| 中文字幕成人| 婷婷久久一区| 日韩a一区二区| 久久久久久久久成人| 国产精品一区高清| 国产黄色一区| 国产精品麻豆久久| 精精国产xxxx视频在线野外| 久久国产免费| 蜜桃一区二区三区在线观看| 亚洲精品在线二区| 麻豆精品视频在线| 免费欧美在线视频| 欧美日韩四区| 日韩大片在线| 国产aa精品| 国内在线观看一区二区三区| 欧美一区激情| 四虎在线精品| 欧美一级一区| 日韩av一二三| 国产精品一区三区在线观看| 日韩精品一级| 国产日韩亚洲|