亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

Starter機(jī)制和springboot整合tomcat

Starter機(jī)制

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

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

那么這個(gè) Starter機(jī)制是怎么運(yùn)作的呢?當(dāng)我們?cè)陧?xiàng)目的pom.xml文件中添加某個(gè)Starter依賴時(shí),其實(shí)就是簡單的添加了很多其他的依賴,比如:

  • 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自動(dòng)配置的原理從META-INF/spring.factories中獲取到tomcat自動(dòng)配置類。通過各種條件注解類判斷是否滿足加載tomcat自動(dòng)配置類的條件。這樣就完成了 Starter機(jī)制

如果我們?cè)陧?xiàng)目中要用Tomcat,那就依賴spring-boot-starter-web就夠了,因?yàn)樗J(rèn)依賴了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的自動(dòng)配置機(jī)制、Starter機(jī)制,條件注解分析等,我們拿一個(gè)實(shí)際的業(yè)務(wù)案例來串講一下,那就是SpringBoot和Tomcat的整合。

我們知道,只要我們的項(xiàng)目添加的starter為:spring-boot-starter-web,那么我們啟動(dòng)項(xiàng)目時(shí),SpringBoot就會(huì)自動(dòng)啟動(dòng)一個(gè)Tomcat。

那么這是怎么做到的呢?

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

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

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

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

那么來看下springboot如何啟動(dòng)web容器的。

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

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

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

重點(diǎn)就是createWebServer();方法。這個(gè)方法中就啟動(dòng)了tomcat

private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			//ServletWebServerFactory 一個(gè)接口  實(shí)現(xiàn)類有TomcatServletWebServerFactory 等等容器工廠
			//通過getWebServerFactory() 獲取到對(duì)應(yīng)容器的創(chuàng)建工廠
			ServletWebServerFactory factory = getWebServerFactory();
			//通過實(shí)現(xiàn)類的getWebServer來啟動(dòng)對(duì)應(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());。我們一步步分析這兩個(gè)方法。

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

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

protected ServletWebServerFactory getWebServerFactory() {
		// Use bean names so that we don't consider the hierarchy
		//獲取到ServletWebServerFactory 所有實(shí)現(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 表示配置了多個(gè)容器
		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);
	}

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

判斷通過后,通過beanName和類型從bean工廠中獲取到唯一的ServletWebServerFactory,然后返回。重點(diǎn)就是ServletWebServerFactory類型的bean是什么時(shí)候配置進(jìn)去的。這個(gè)就是涉及到web的自動(dòng)配置類。

在MATE-INF/spring.factories中有一個(gè)ServletWebServerFactoryAutoConfiguration的自動(dòng)配置類。

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

@ConfigurationProperties注解會(huì)從配置文件中讀取對(duì)應(yīng)的信息到ServerProperties的屬性上,所以我們?cè)谂渲梦募x端口號(hào),地址等等就會(huì)被識(shí)別。

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

EmbeddedTomcat.class定義了TomcatServletWebServerFactory,所以回到之前的getWebServerFactory(),拿到的就是TomcatServletWebServerFactory。然后調(diào)用factory.getWebServer來啟動(dòng)容器。實(shí)際上就是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);
	}

這個(gè)方法一目了然,就是new Tomcat(),然后啟動(dòng)。

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

總結(jié)

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

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

相關(guān)文章

最新評(píng)論