一直使用Tomcat确不知道它的运行原理。看了源码后对它的启动过程有了一定的了解,特来记录一下。
首先先介绍一下Tomcat的架构图:
Tomcat主要有两个核心的组件,一个是Connector(连接器)和容器。所谓连接器就是当有HTTP请求到来时,连接器负责接收这个请求,然后将该请求转发到容器。容器有Engine,Host,Context,Wrapper。Engine:表示整个Catalina servlet引擎;Host:表示包含一个或多个Context容器的虚拟主机;Context:表示一个Web应用程序。一个Context可以有多个Wrapper;Wrapper:表示一个独立的servlet。一个容器可以有0个或多个低层级的子容器。例如,一般情况下,一个Context实例会有一个或多个Wrapper实例。一个Host实例中会有0个或多个Context实例。但是,Wrapper类型处于层级结构的最底层,因此,它无法再包含子容器了。
一般启动Tomcat会是运行startup.bat或者startup.sh文件,这两个文件最后都会调用,org.apache.catalina.startup包下面Bootstrap类的main方法。main方法具体实现如下:
main方法先实例化了一个Bootstrap实例,接着调用了init方法。init方法是生命周期方法,以后不再累述。接着看init的具体实现。
init方法,先初始化了类加载器。initClassLoaders方法具体实现如下:
createClassLoader具体实现细节不再显示,有感兴趣的读者可以具体查看。该方法的具体签名为:
private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception
从方法签名中可以看出createClassLoader需要传入一个父加载器。从具体的代码中可以看出,commonLoader类加载器是catalinaLoader类加载器和sharedLoader类加载器的父加载器。初始化完类加载器后,使用反射机制调用org.apache.catalina.startup.Catalina类下的setParentClassLoader方法。具体代码是:
因为Tomcat执行的是start操作,调用完init方法后,会执行load方法。
load方法通过反射调用Catalina类的load方法。
Catalina类的load方法:
load方法中比较重要的方法是createStartDigester(),createStartDigester方法主要的作用就是帮我们实例化了所有的服务组件包括server,service和connect。具体的实例化方法,
初始化操作完成后,接下来会执行catalina实例的start方法。
从上面加载的组件中,Tomcat会默认加载org.apache.catalina.core.StandardServer作为Server的实例类。
在Server的start的方法里面会执行service的start方法。在createStartDigester()方法里面,会默认加载org.apache.catalina.core.StandardService类。会接着调用Service的start方法。
service中会调用connector的start方法。至此Tomcat启动完毕