private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
//獲取到使用的web容器
ServletWebServerFactory factory = getWebServerFactory();
//啟動(dòng)web容器
this.webServer = factory.getWebServer(getSelfInitializer());
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
//根據(jù)bean的定義,獲取到ServletWebServerFactory類(lèi)型的bean名稱
//這里是獲取的bean名字,這一步bean對(duì)象可能還沒(méi)有創(chuàng)建,因?yàn)橐扰袛郤ervletWebServerFactory類(lèi)型的bean有幾個(gè),如果有0個(gè)或者2個(gè)及以上,那么或報(bào)錯(cuò),就不用創(chuàng)建bean對(duì)象了
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));
}
//創(chuàng)建web容器的bean對(duì)象,并返回
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
//TomcatServletWebServerFactory#getWebServer
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
//new一個(gè)Tomcat并進(jìn)行各種設(shè)置
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
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);
}
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
}
//生成TomcatWebServer并啟動(dòng)
public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
initialize();
}
private void initialize() throws WebServerException {
//啟動(dòng)Tomcat
this.tomcat.start();
內(nèi)嵌的web容器的配置
在ServletWebServerFactoryConfiguration中,存在幾個(gè)內(nèi)部類(lèi),這些內(nèi)部類(lèi)只有滿足ConditionalOnClass的條件,才會(huì)生效,比如EmbeddedTomcat,只有pom文件中有Tomcat的依賴,EmbeddedTomcat才會(huì)生效。但是如果pom中有超過(guò)一個(gè)的web容器的配置,那么也會(huì)報(bào)錯(cuò)。
上面getWebServerFactory中獲取bean的name,web容器的bean名稱就出自這里。
@Configuration
class ServletWebServerFactoryConfiguration {
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class,
search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
WebAppContext.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class,
search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyServletWebServerFactory JettyServletWebServerFactory() {
return new JettyServletWebServerFactory();
}
}
/**
* Nested configuration if Undertow is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class,
search = SearchStrategy.CURRENT)
public static class EmbeddedUndertow {
@Bean
public UndertowServletWebServerFactory undertowServletWebServerFactory() {
return new UndertowServletWebServerFactory();
}
}
}