一、软件版本
Spring Boot:2.0.1.RELEASE
Tomcat:8.5.16
二、Tomcat启动UML解析
![](https://img.haomeiwen.com/i10812661/506400266316a8a8.png)
三、Tomcat启动代码解析
1、SpringApplication内部流程
(1)public ConfigurableApplicationContext run(String... args) {
...
refreshContext(context);//刷新上下文
...
}
(2)private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
(3)protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
2、AbstractApplicationContext内部流程
(4)public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
...
} finally {
this.resetCommonCaches();
}
}
}
(5)protected void onRefresh() throws BeansException {
}
3、ServletWebServerApplicationContex内部流程
@Override
(5)protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
(6)private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
//启动服务器
(9)private WebServer startWebServer() {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.start();
}
return webServer;
}
4、TomcatServletWebServerFactory内部流程
@Override
(7)public WebServer getWebServer(ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null ? this.baseDirectory
: createTempDir("tomcat"));
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
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
(8)return getTomcatWebServer(tomcat);
}
四、补充说明
1、Tomcat相关的配置类
Spring通过ServletWebServerFactoryCustomizer,TomcatServletWebServerFactoryCustomizer, TomcatWebServerFactoryCustomizer三个配置类对tomcat完成配置。
ServletWebServerFactoryConfiguration
@Configuration
class ServletWebServerFactoryConfiguration {
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class,
search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
//定义TomcatServletWebServerFactory的bean definition
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
...
...
...
}
ServletWebServerFactoryAutoConfiguration
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
// 主要配置通用的 servlet 的信息,包含端口、上下文路径、应用名、Session配置、Servlet 携带的初始变量等等
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
//配置tomcat的额外信息,redirectContextRoot(是否在请求根上下文时转发,true则转发路径为/demoWeb/)和useRelativeRedirects(是否使用相对路径)等路径跳转问题处理
@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
...
...
...
}
EmbeddedWebServerFactoryCustomizerAutoConfiguration
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
/**
* Nested configuration if Tomcat is being used.
*/
@Configuration
@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerFactoryCustomizerConfiguration {
//配置tomcat的主要信息,包含 remoteIpValue、connector(最大/最小可接收线程、最大可接收头部大小等等)、uriEncoding、connectionTimeout、maxConnection等属性
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
...
...
...
}
2、ServletContextInitializer说明
在ServletWebServerApplicationContext中有一段getWebServer(getSelfInitializer())代码,
getWebServer的参数为函数式接口,getSelfInitializer()返回的函数内容为:selfInitialize,作用:注册所有的 servlet 组件 (包括 Servlet,Filter,Listener),源码如下:
/**
* Returns the {@link ServletContextInitializer} that will be used to complete the
* setup of this {@link WebApplicationContext}.
* @return the self initializer
* @see #prepareWebApplicationContext(ServletContext)
*/
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}
private void selfInitialize(ServletContext servletContext) throws ServletException {
prepareWebApplicationContext(servletContext);
registerApplicationScope(servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),
servletContext);
// 这一步是获取所有的 servlet 组件
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}
ServletContextInitializer是一个函数式接口,源码如下:
@FunctionalInterface
public interface ServletContextInitializer {
/**
* Configure the given {@link ServletContext} with any servlets, filters, listeners
* context-params and attributes necessary for initialization.
* @param servletContext the {@code ServletContext} to initialize
* @throws ServletException if any call against the given {@code ServletContext}
* throws a {@code ServletException}
*/
void onStartup(ServletContext servletContext) throws ServletException;
}
五、参考文章
1、https://www.jianshu.com/p/6d6d2e47bf41
2、https://www.jianshu.com/p/fa44510230a2
网友评论