<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
從原始碼層面理解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內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45