在springboot中,是融合了tomcat的启动与加载的,那么关于tomcat的启动与加载的入口就是研究的第一步,在EmbeddedWebApplicationContext类中,重写了AbstractApplicationContext的finishRefresh()方法,如下:
protected void finishRefresh() { super.finishRefresh(); EmbeddedServletContainer localContainer = startEmbeddedServletContainer(); if (localContainer != null) { publishEvent( new EmbeddedServletContainerInitializedEvent(this, localContainer)); } }在finishRefresh方法中,第二行的startEmbeddedServletContainer()方法就是tomcat启动的入口,我们进入入口看下:
private EmbeddedServletContainer startEmbeddedServletContainer() { EmbeddedServletContainer localContainer = this.embeddedServletContainer; if (localContainer != null) { localContainer.start(); } return localContainer; }在这个入口中,是通过embeddedServeletContainer类型的start()方法进入下一步的,这个embeddedServeletContainer类型是TomcatEmbeddedServletContainer,这个属性的赋值是在onrefresh方法中:
protected void onRefresh() { super.onRefresh(); try { createEmbeddedServletContainer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start embedded container", ex); } }代码在start()方法中就进入了TomcatEmbeddedServletContainer的start()方法,关于TomcatEmbeddedServletContainer的类图如下:
EmbeddedServletContainer是tomcat中非常重要的一个类型,关于这个类型的示例,有一篇非常比错不错的文章,可供大家参考以及搞明白这个类型的作用:
深入SpringBoot:自定义EmbeddedServletContainer
在后面沿着代码进去,会调用了service.addConnector,此处用的是标准的service即是StandardService。在这个方法中调用了connector.start();方法,这个方法调用了父类LifecycleBase类的start()方法,关于LifecycleBase类是tomcat组件管理中非常重要的一个类型,负责组件的启动,停止等操作。然后在方法:startInternal();中调用回了Connector的startInternal()方法:
@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.start();,这个方法中protocolHandler类型是:Http11NioProtocol,其类型定义在Connector的如下代码中:
/** * Coyote Protocol handler class name. * Defaults to the Coyote HTTP/1.1 protocolHandler. */ protected String protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";在此,普及一下tomcat类中的知识,在Connector中有一属性非常重要,就是protocol,这个属性决定了Connector用哪种方式与客户端连接,springboot1.5中默认使用的是Http11NioProtocol,而在protocol中也有一个非常重要的属性是endpoint,关于endpoint是接收非配socket的连接点了,至关重要, 这里有篇文章介绍了endpoint,非常好。在endpoint的start方法中做了端口接听,以及读写数据等等与客户端的交互工作。至此,在springboot的内置tomcat的入口就找到了。
最后再介绍一个tomcat相关的几个重要组件:
- Server,默认是使用StandardServer,这个类是Lifecycle的子类,是tomcat启动的第一个组件。
- Service,在Server属性中,tomcat紧接着Server启动的服务组件。
- Engine,默认使用StandardEngine,一个engine表示为特定的服务请求处理流水线。由于服务可能有多个连接器,引擎会接收并处理来自这些连接器的所有请求,并将响应传递回适当的连接器以传输给客户端。该engine interface可以实现提供自定义的发动机,虽然这种情况并不常见。
- Host,默认实现StandardHost,负责处理地址或者域名。