Tomcat源码分析(一)--服务启动
对Tomcat感兴趣是由于《深入理解Tomcat》这本书,之前仅仅是使用到了Tomcat,这本书却让我对Tomcat的实现理解的更加透彻了,在这里希望记录一些自己对Tomcat的理解。由于这本书是基于tomcat4的,所以我的文章也是基于tomcat4的,但是tomcat的核心思想应该是没有变的,最主要的两个组件还是连接器和容器。主要为了学习,就不管是新版本还是旧版本了。
为了后面的理解,先大致说一下Tomcat的整体架构,Tomcat主要有两个组件,连接器和容器,所谓连接器就是一个http请求过来了,连接器负责接收这个请求,然后转发给容器。容器即servlet容器,容器有很多层,分别是Engine,Host,Context,Wrapper。最大的容器Engine,代表一个servlet引擎,接下来是Host,代表一个虚拟机,然后是Context,代表一个应用,Wrapper对应一个servlet。从连接器传过来连接后,容器便会顺序经过上面的容器,最后到达特定的servlet。要说明的是Engine,Host两种容器在不是必须的。(本来想弄张图的,但是不知道csdn怎么搞的,插不进去.),实际上一个简单的tomcat只要连接器和容器就可以了,但tomcat的实现为了统一管理连接器和容器等组件,额外添易做图务器组件(server)和服务组件(service),添加这两个东西的原因我个人觉得就是为了方便统一管理连接器和容器等各种组件。一个server可以有多个service,一个service包含多个连接器和一个容器,当然还有一些其他的东西,一个父容器又可以包含多个子容器,这些被统一管理的组件都实现了Lifecycle接口。只要一个组件启动了,那么他的所有子组件也会跟着启动,比如一个server启动了,它的所有子service都会跟着启动,service启动了,它的所有连接器和容器等子组件也跟着启动了,这样,tomcat要启动,只要启动server就行了,其他的组件都会跟随着启动,那么server是如何启动的?再让我们从头来看...
一般启动Tomcat会是运行startup.bat或者startup.sh文件,实际上这两个文件最后会调用org.apache.catalina.startup.Bootstrap类的main方法,这个main方法主要做了两件事情,1:定义和初始化了tomcat自己的类加载器,2:通过反射调用了org.apache.catalina.startup.Catalina的process方法;关键代码如下:
[java]
ClassLoader commonLoader = null;
ClassLoader catalinaLoader = null;
ClassLoader sharedLoader = null;
..............................初始化以上三个类加载器
Class startupClass =catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
......................................
methodName = "process";//方法名
paramTypes = new Class[1];
paramTypes[0] = args.getClass();
paramValues = new Object[1]
paramValues[0] = args;
method =startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);//调用process方法
org.apache.catalina.startup.Catalina的process方法很短,就是下面一点东西:
[java]
public void process(String args[]) {
setCatalinaHome();
setCatalinaBase(); www.zzzyk.com
try {
if (arguments(args))
execute();
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
process的功能也很简单,1:如果catalina.home和catalina.base两个属性没有设置就设置一下,2:参数正确的话就调用execute方法,execute的方法就是简单的调用start方法,其中在判断参数正确的方法arguments中会设置starting标识为true,这样在execute方法中就能调用start方法,start方法是重点,在它里面启动了我们的Tomcat所有的服务,下面是start方法里面一些关键的代码:
[java]
protected void start() {
Digester digester = createStartDigester();
File file = configFile();
try {
InputSource is =
new InputSource("file://" + file.getAbsolutePath());
FileInputStream fis = new FileInputStream(file);
is.setByteStream(fis);
digester.push(this);
digester.parse(is);
fis.close();
} catch (Exception e) {
System.out.println("Catalina.start: " + e);
e.printStackTrace(System.out);
System.exit(1);
}
........................
Thread shutdownHook = new CatalinaShutdownHook();
// Start the new server
if (server instanceof Lifecycle) {
try {
server.initialize();
((Lifecycle) server).start();
try {
// Register shutdown hook
Runtime.getRuntime().addShutdownHook(shutdownHook);
} catch (Throwable t) {
// This will fail on JDK 1.2. Ignoring, as Tomcat can run
// fine without the shutdown hook.
}
// Wait for the server to be told to shut down
server.await();
} catch (LifecycleException e) {
&n
补充:软件开发 , Java ,