欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot Starter機制及整合tomcat的實現(xiàn)詳解

 更新時間:2022年09月08日 10:39:30   作者:天黑請閉眼丶風(fēng)  
這篇文章主要介紹了SpringBoot Starter機制及整合tomcat的實現(xiàn),我們知道SpringBoot自己在“后臺”幫我們配置了很多原本需要我們手動去的東西,至于這個“后臺”是啥,就是Starter機制

Starter機制和springboot整合tomcat

Starter機制

先解釋一下什么是Starter機制。Starter機制就是maven工程中pom文件引入了某個Starter依賴,就能使用對應(yīng)的功能 例如 引入web的starter依賴 ,就可以使用有關(guān)于web方面的功能。

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

那么這個 Starter機制是怎么運作的呢?當(dāng)我們在項目的pom.xml文件中添加某個Starter依賴時,其實就是簡單的添加了很多其他的依賴,比如:

  • spring-boot-starter-web:引入了spring-boot-starter、spring-boot-starter-json、spring-boot-starter-tomcat等和Web開發(fā)相關(guān)的依賴包
  • spring-boot-starter-tomcat:引入了tomcat-embed-core、tomcat-embed-el、tomcat-embed-websocket等和Tomcat相關(guān)的依賴包

通過springboot自動配置的原理從META-INF/spring.factories中獲取到tomcat自動配置類。通過各種條件注解類判斷是否滿足加載tomcat自動配置類的條件。這樣就完成了 Starter機制

如果我們在項目中要用Tomcat,那就依賴spring-boot-starter-web就夠了,因為它默認依賴了spring-boot-starter-tomcat,從而依賴了Tomcat,從而Tomcat相關(guān)的Bean能生效。

而如果不想用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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>

springboot整合tomcat

通過前面SpringBoot的自動配置機制、Starter機制,條件注解分析等,我們拿一個實際的業(yè)務(wù)案例來串講一下,那就是SpringBoot和Tomcat的整合。

我們知道,只要我們的項目添加的starter為:spring-boot-starter-web,那么我們啟動項目時,SpringBoot就會自動啟動一個Tomcat。

那么這是怎么做到的呢?

首先我們可以發(fā)現(xiàn),在spring-boot-starter-web這個starter中,其實間接的引入了spring-bootstarter-tomcat這個starter,這個spring-boot-starter-tomcat又引入了tomcat-embed-core依賴,

所以只要我們項目中依賴了spring-boot-starter-web就相當(dāng)于依賴了Tomcat。

從這個spring-boot-starter-web依賴中引入了tomcat的依賴

又從tomcat的依賴中引入了tomcat相關(guān)的依賴

那么來看下springboot如何啟動web容器的。

首先我們知道springboot啟動通過SpringApplication.run(MyApplication.class, args);,進入run方法,會調(diào)到如下代碼

這個run方法中的有一個refreshContext(context);方法。refreshContext(context);方法經(jīng)過一系列調(diào)用到ServletWebServerApplicationContextonRefresh()方法

@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			// 啟動Tomcat
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}

重點就是createWebServer();方法。這個方法中就啟動了tomcat

private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			//ServletWebServerFactory 一個接口  實現(xiàn)類有TomcatServletWebServerFactory 等等容器工廠
			//通過getWebServerFactory() 獲取到對應(yīng)容器的創(chuàng)建工廠
			ServletWebServerFactory factory = getWebServerFactory();
			//通過實現(xiàn)類的getWebServer來啟動對應(yīng)的容器
			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();
	}

createWebServer();中核心代碼是ServletWebServerFactory factory = getWebServerFactory();this.webServer = factory.getWebServer(getSelfInitializer());。我們一步步分析這兩個方法。

首先ServletWebServerFactory 是一個接口,它的實現(xiàn)類有

那么它會用到哪個實現(xiàn)類呢?這個就和ServletWebServerFactory factory = getWebServerFactory();方法有關(guān)

protected ServletWebServerFactory getWebServerFactory() {
		// Use bean names so that we don't consider the hierarchy
		//獲取到ServletWebServerFactory 所有實現(xiàn)類的bean的名稱 也就是springboot中配置了哪些容器 如tomcat jetty等
		String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
		//如果沒有bean 表示沒有配置容器
		if (beanNames.length == 0) {
			throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
					+ "ServletWebServerFactory bean.");
		}
		//如果bean大于1 表示配置了多個容器
		if (beanNames.length > 1) {
			throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
					+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
		}
		//最終返回唯一的容器工廠 比如配置了tomcat 那么就返回了TomcatServletWebServerFactory
		return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
	}

這個方法中,先獲取所有ServletWebServerFactory類型的beanName,如果為空或者大于一個,就會拋異常,也就是說如果配置了tomcat又配置jetty,就會有兩個ServletWebServerFactory類型的beanName,那么就會拋出異常。

判斷通過后,通過beanName和類型從bean工廠中獲取到唯一的ServletWebServerFactory,然后返回。重點就是ServletWebServerFactory類型的bean是什么時候配置進去的。這個就是涉及到web的自動配置類。

在MATE-INF/spring.factories中有一個ServletWebServerFactoryAutoConfiguration的自動配置類。

@EnableConfigurationProperties(ServerProperties.class)注解會去加載ServerProperties

@ConfigurationProperties注解會從配置文件中讀取對應(yīng)的信息到ServerProperties的屬性上,所以我們在配置文件定義端口號,地址等等就會被識別。

ServletWebServerFactoryAutoConfiguration的自動配置類通過@Import注解導(dǎo)入了ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,

EmbeddedTomcat.class定義了TomcatServletWebServerFactory,所以回到之前的getWebServerFactory(),拿到的就是TomcatServletWebServerFactory。然后調(diào)用factory.getWebServer來啟動容器。實際上就是TomcatServletWebServerFactory的getWebServer方法

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());
		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);
		return getTomcatWebServer(tomcat);
	}

這個方法一目了然,就是new Tomcat(),然后啟動。

這大致就是springboot整合tomcat的流程。如果整合的是jetty,那么拿到的ServletWebServerFactory類型就是JettyServletWebServerFactory,過程是一樣的。

總結(jié)

springboot整合tomcat的過程中,首先通過依賴導(dǎo)入了tomcat的相關(guān)依賴。通過ServletWebServerFactoryAutoConfiguration自動配置類,加載EmbeddedTomcat,也就是加載了TomcatServletWebServerFactory。通過TomcatServletWebServerFactory的getWebServer方法啟動tomcat。

到此這篇關(guān)于SpringBoot Starter機制及整合tomcat的實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)SpringBoot Starter機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論