spring-boot-web中web容器叫WebServer(org.springframework.boot.web.server.WebServer),由WebServerFactory(org.springframework.boot.web.server.WebServerFactory)创建,WebServer支持多种web容器,tomcat是默认使用的容器。
spring-boot-web中tomcat容器叫TomcatWebServer(org.springframework.boot.web.embedded.tomcat.TomcatWebServer),是tomcat(org.apache.catalina.startup.Tomcat)在Spring中的代理,由TomcatReactiveWebServerFactory(org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory)创建。
spring容器在启动的过程中根据ServletWebServerFactoryAutoConfiguration构建相应的BeanDefinition,其中就有TomcatServletWebServerFactory。
Spring容器ServletWebServerApplicationContext中通过onRefresh()方法创建了WebServer,通过finishRefresh()方法启动WebServer,开始对外提供服务。
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
@Override
protected void finishRefresh() {
super.finishRefresh();
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
对createWebServer进行分析
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
//拿到一个工厂类对象
ServletWebServerFactory factory = getWebServerFactory();
//创建相应的webServer
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();
}
对TomcatServletWebServerFactory中getWebServer进行分析
@Override
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);
//创建TomcatWebServer对象
return getTomcatWebServer(tomcat);
}
对startWebServer进行分析
private WebServer startWebServer() {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.start();
}
return webServer;
}
对TomcatWebServer中start()进行分析
@Override
public void start() throws WebServerException {
synchronized (this.monitor) {//同步锁
if (this.started) {
return;
}
try {
//关键代码
addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
performDeferredLoadOnStartup();
}
checkThatConnectorsHaveStarted();
this.started = true;
TomcatWebServer.logger
.info("Tomcat started on port(s): " + getPortsDescription(true)
+ " with context path '" + getContextPath() + "'");
}
catch (ConnectorStartFailedException ex) {
stopSilently();
throw ex;
}
catch (Exception ex) {
throw new WebServerException("Unable to start embedded Tomcat server",
ex);
}
finally {
Context context = findContext();
ContextBindings.unbindClassLoader(context, context.getNamingToken(),
getClass().getClassLoader());
}
}
}
private void addPreviouslyRemovedConnectors() {
Service[] services = this.tomcat.getServer().findServices();
for (Service service : services) {
Connector[] connectors = this.serviceConnectors.get(service);
if (connectors != null) {
for (Connector connector : connectors) {
//关键代码
service.addConnector(connector);
if (!this.autoStart) {
stopProtocolHandler(connector);
}
}
this.serviceConnectors.remove(service);
}
}
}
StandardService
@Override
public void addConnector(Connector connector) {
synchronized (connectorsLock) {
connector.setService(this);
Connector results[] = new Connector[connectors.length + 1];
System.arraycopy(connectors, 0, results, 0, connectors.length);
results[connectors.length] = connector;
connectors = results;
if (getState().isAvailable()) {
try {
connector.start();
} catch (LifecycleException e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
// Report this property change to interested listeners
support.firePropertyChange("connector", null, connector);
}
}
最终走到了Connector(org.apache.catalina.connector.Connector)中
@Override
protected void startInternal() throws LifecycleException {
// Validate settings before starting
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
setState(LifecycleState.STARTING);
try {
//关键代码
protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
}
ProtocolHandler:用来处理Socket相关的东西
最终走到了类org.apache.tomcat.util.net.AbstractEndpoint。
在AbstractEndpoint的一个实现类中有这样一段代码:
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
// Loop until we receive a shutdown command
while (running) {
// Loop if endpoint is paused
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore
}
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
//if we have reached max connections, wait
countUpOrAwaitConnection();
AsynchronousSocketChannel socket = null;
try {
// Accept the next incoming connection from the server
// socket
//接收网络请求
socket = serverSock.accept().get();
} catch (Exception e) {
// We didn't get a socket
countDownConnection();
if (running) {
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw e;
} else {
break;
}
}
// Successful accept, reset the error delay
errorDelay = 0;
// Configure the socket
if (running && !paused) {
// setSocketOptions() will hand the socket off to
// an appropriate processor if successful
//处理网络请求
if (!setSocketOptions(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}