上一篇写了tomcat处理请求时和spring boot配合的过程,这次我们单独把tomcat处理请求的详细过程
一个Tomcat 中只有一个Server, 一个Server 可以包含多个Service
一个Service 只有一个Container, 但可以有多个Connectors (因为一个服务可以有多个连接,如同时提供http 和https 连接,也可以提供相同协议不同端口的连接)。
Tomcat 里的Server 由org.apache.catalina.startup.Catalina 来管理, Catalina 是整个Tomcat的管理类,它里面的三个方法load 、start 、stop 分别用来管理整个服务器的生命周期。
load 方法用于根据conf/server.xml 文件创建Server 并调用Server 的init 方法进行初始化,
start方法用于启动服务器
stop 方法用于停止服务器,
start 和stop 方法在内部分别调用了Server 的start和stop 方法, load 方法内部调用了Server 的init 方法,这三个方法都会按容器的结构逐层调用相应的方法,比如, Server 的start 方法中会调用所有的Service 中的start 方法。这就是Tomcat 生命周期的管理方式Catalina 还有个方法也很重要,那就是await 方法, Catalina 中的await 方法直接调用了Server 的await 方法,这个方法的作用是进入一个循环,让主线程不会退出。
再说下tomcat启动问题,在springboot中,1.0版本和2.0版本启动tomcat源码是不一样的,这里是springboot2的启动:application.run()方法里:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//略。。。。。
refreshContext(context);//点击进入。。。。。。。。。。。
afterRefresh(context, applicationArguments);
//略。。。。
return context;
}
进入refreshContext方法:(在spring boot1应该是EmbeddedWebApplicationContext 子类执行这个方法)
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//略。。。。1
onRefresh();//点击进入
//略
}
}
进入类ServletWebServerApplicationContext的onRefresh()方法:
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();//点击进入。。。。。。
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
//点击createWebServer()方法
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();
}
createWebServer()方法里
//2.4.1 点击进入
ServletWebServerFactory factory = getWebServerFactory();
//2.4.2点击进入
this.webServer = factory.getWebServer(getSelfInitializer());
2.4.1 getWebServerFactory() 根据上文1.1里结论会返回TomcatServletWebServerFactory。所以2.4.2的factory.getWebServer(getSelfInitializer())中的factory是指TomcatServletWebServerFactory,点击进入实现类TomcatServletWebServerFactory的getWebServer(getSelfInitializer())方法。
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);
return getTomcatWebServer(tomcat);//点击进入。。。。。。。。
}
//点击进入getTomcatWebServer(tomcat)
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0);//点击进入
}
//点击new TomcatWebServer
public TomcatWebServer(Tomcat tomcat, boolean autoStart