Tomcat代码学习日记系列.

 Tomcat代码学习日记系列. (本贴只接受技术型讨论)
Getting started.         准备工作
    决定利用一段时间系统的来研究tomcat源码, 希望大家积极参与.
    每周五,我争取把写一篇内读源码的体会.
    准备工作: 下载Tomcat528 由于528是一个比较稳定的版本, 我们就从它开始. http://archive.apache.org/dist/jakarta/tomcat-5/v5.0.28/src/jakarta-tomcat-5.0.28-src.zip开始.

    下载 eclipse ide   www.eclipse.org   
    配置好eclipse后, 新建一个java工程tomcatcode. 采用src/bin 组织结构.
     下载源码的目录下搜索org . 然后把所有得到的文件夹全部copy 到eclispe/workspace/tomcatcode/src/ 目录下, 启动eclipse刷新工程tomcatcode/src目录.  
    休息一下, 经过很多编译错误后, 记得要导入以下jar包.
     搜索tomcat安装目录下, *.jar ,  把这些jar包统统导入.tomcatcode工程中.

     OK 现在错误已经减少到基本可以接受的程度了, 不会影响我们阅读代码了.


     我们将从以下文件开始, %Tomcat_home%/bin下的 startup.bat, startup.sh. 进一步阅读我们还会接触到.该目录下的bootstrap.jar
     第一篇日记里, 我们将从org.apache.catalina.startup.Bootstrap 开始
 
天堂在哪里?
<script type="text/javascript"> <!-- google_ad_client = 'pub-4196225375348397';google_ad_width = 468;google_ad_height = 60;google_ad_format = '468x60_as';google_ad_channel ='6300525099';google_color_border = 'CCCCCC';google_color_bg = 'FFFFFF';google_color_link = '000000';google_color_url = '666666';google_color_text = '333333';//--> </script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-4196225375348397&dt=1114703851652&lmt=1114703851&prev_fmts=728x90_as&format=468x60_as&output=html&channel=6300525099&url=http%3A%2F%2Fwww.matrix.org.cn%2Fforum_view.asp%3Fforum_id%3D27%26view_id%3D17007&color_bg=FFFFFF&color_text=333333&color_link=000000&color_url=666666&color_border=CCCCCC&ref=http%3A%2F%2Fwww.matrix.org.cn%2Fjava.asp&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=16&u_tz=480&u_java=true" frameborder="0" width="468" scrolling="no" height="60" allowtransparency="65535">
 本贴发表时间:2005-3-2 18:20:00  

Java文栏:ROR历险记
jinchen 
等级: 论坛版主
头衔:不是天使
贴子:59
积分:75
Matrix币:0
注册:2005-2-23
          2
 
Tomcat源码学习日记第一周 startup week1
 

从startup.bat开始.
找到%TOMCAT_HOME%/bin  目录下的startup.dat文件, 用文本编辑器(notepad, editplus, ultraedit等)打开

@echo off
if "%OS%" == "Windows_NT" setlocal
rem ---------------------------------------------------------------------------
rem Start script for the CATALINA Server
rem
rem $Id: startup.bat,v 1.6 2004/05/27 18:25:11 yoavs Exp $
rem ---------------------------------------------------------------------------

rem Guess CATALINA_HOME if not defined
set CURRENT_DIR=%cd%
if not "%CATALINA_HOME%" == "" goto gotHome
set CATALINA_HOME=%CURRENT_DIR%
if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome
cd ..
set CATALINA_HOME=%cd%
cd %CURRENT_DIR%
:gotHome
if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome

set EXECUTABLE=%CATALINA_HOME%/bin/catalina.bat

rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find %EXECUTABLE%
echo This file is needed to run this program
goto end
:okExec

rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs

call "%EXECUTABLE%" start %CMD_LINE_ARGS%

:end


快速浏览一下, 发现它做了以下事情, 寻找系统环境变量中是否有CATALINA_HOME  如果没有就赋给它当前目录
设置一个执行标签  set EXECUTABLE=%CATALINA_HOME%/bin/catalina.bat
检查bin目录下是否含有catalina.bat  文件, 如果没有给出适当的信息.

...执行bin目录(指tomcat安装目录下bin目录) catalina.bat  
call "%EXECUTABLE%" start %CMD_LINE_ARGS%

unix/linux 环境下

查看bin目录下startup.sh
#!/bin/sh
# -----------------------------------------------------------------------------
# Start Script for the CATALINA Server
#
# $Id: startup.sh,v 1.3 2002/08/04 18:19:43 patrickl Exp $
# -----------------------------------------------------------------------------

# resolve links - $0 may be a softlink
PRG="$0"

while [ -h "$PRG" ] ; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> /(.*/)$'`
  if expr "$link" : '.*/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done
 
PRGDIR=`dirname "$PRG"`
EXECUTABLE=catalina.sh

# Check that target executable exists
if [ ! -x "$PRGDIR"/"$EXECUTABLE" ]; then
  echo "Cannot find $PRGDIR/$EXECUTABLE"
  echo "This file is needed to run this program"
  exit 1
fi

exec "$PRGDIR"/"$EXECUTABLE" start "$@"

这是一个unix/linux  shell编程脚本.  功能与startup.bat类似, 不过这里做了一个有关文件连接的处理.然后调用
catalina.sh   
unix/linux 环境以后不再说明比较还要了解一些必要的操作系统相关知识.

查看bin目录下catalina.bat (篇幅有限这里不再给出文件的全部代码,请到相关目录查看)

   不要被它唬住了, 其实没什么太困难的东西.   让我们仔细看一下.
   顺便说一句,读代码, 不要指望一次把所有的东西都理解,(基本上这不可能,一时不明白的就放放吧.)
   
rem 是批处理命令中 类似注释的意思,  我们把startup.bat 和 catalina.bat 文件第一行 @echo off命令
前面加一个 rem   : 改为 rem @echo off   (为了理解tomcat启动过程,我们打开echo输出, 现在执行startup.bat 看看dos输出什么了)

运行 cmd , cd d:/tmcat528/bin,   startup  
我给这些输出加了一些简单的注释,    用/**/ 和// 表示 同c++和java的注释语法 
D:/Tomcat528/bin>startup.bat

D:/Tomcat528/bin>rem @echo off
//如果是winnt操作系统, 则对这次环境变量的设置只对当前批处理文件有效
D:/Tomcat528/bin>if "Windows_NT" == "Windows_NT" setlocal

D:/Tomcat528/bin>rem -----------------------------------------------------------
----------------
/*
 以下是一些欢迎版本等信息.
*/
D:/Tomcat528/bin>rem Start script for the CATALINA Server

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem $Id: startup.bat,v 1.6 2004/05/27 18:25:11 yoavs Exp $

D:/Tomcat528/bin>rem -----------------------------------------------------------
----------------
//判断CATALINA_HOME 是否已经设置
D:/Tomcat528/bin>rem Guess CATALINA_HOME if not defined

D:/Tomcat528/bin>set CURRENT_DIR=D:/Tomcat528/bin

D:/Tomcat528/bin>if not "D:/Tomcat528" == "" goto gotHome

D:/Tomcat528/bin>if exist "D:/Tomcat528/bin/catalina.bat" goto okHome

D:/Tomcat528/bin>set EXECUTABLE=D:/Tomcat528/bin/catalina.bat

D:/Tomcat528/bin>rem Check that target executable exists
//设置执行标签
D:/Tomcat528/bin>if exist "D:/Tomcat528/bin/catalina.bat" goto okExec

D:/Tomcat528/bin>rem Get remaining unshifted command line arguments and save the
m in the

D:/Tomcat528/bin>set CMD_LINE_ARGS=

D:/Tomcat528/bin>if """" == """" goto doneSetArgs
//执行catalina.bat 
D:/Tomcat528/bin>call "D:/Tomcat528/bin/catalina.bat" start

D:/Tomcat528/bin>rem @echo off

D:/Tomcat528/bin>if "Windows_NT" == "Windows_NT" setlocal

D:/Tomcat528/bin>rem -----------------------------------------------------------
----------------

D:/Tomcat528/bin>rem Start/Stop Script for the CATALINA Server

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem Environment Variable Prequisites

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   CATALINA_HOME   May point at your Catalina "build" directory.

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   CATALINA_BASE   (Optional) Base directory for resolving dynamic portions

D:/Tomcat528/bin>rem                   of a Catalina installation.  If not present, resolves to

D:/Tomcat528/bin>rem                   the same directory that CATALINA_HOME points to.

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   CATALINA_OPTS   (Optional) Java runtime options used when the "start",

D:/Tomcat528/bin>rem                   "stop", or "run" command is executed.

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   CATALINA_TMPDIR (Optional) Directory path location of temporary directory

D:/Tomcat528/bin>rem                   the JVM should use (java.io.tmpdir).  Def
aults to

D:/Tomcat528/bin>rem                   d:/Tomcat528/temp.

D:/Tomcat528/bin>rem
//这就是说启动Tomcat要求你必须装好JDK (Java Development Kit)并且设置好 %JAVA_HOME%才能启动
D:/Tomcat528/bin>rem   JAVA_HOME       Must point at your Java Development Kit installation.

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   JAVA_OPTS       (Optional) Java runtime options used when the "start",

D:/Tomcat528/bin>rem                   "stop", or "run" command is executed.

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   JSSE_HOME       (Optional) May point at your Java Secure
Sockets Extension
//看起来好像是把自定义的jar文件放在这里,系统讲自动装载.
D:/Tomcat528/bin>rem                   (JSSE) installation, whose JAR files will be added to the

D:/Tomcat528/bin>rem                   system class path used to start Tomcat.

D:/Tomcat528/bin>rem
Java 平台调试器体系结构(Java Platform Debugger Architecture,JPDA)看起来像有关调试的一些控制. 我们先不管它
D:/Tomcat528/bin>rem   JPDA_TRANSPORT  (Optional) JPDA transport used when the "jpda start"

D:/Tomcat528/bin>rem                   command is executed. The default is "dt_shmem".

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem   JPDA_ADDRESS    (Optional) Java runtime options used when the "jpda start"

D:/Tomcat528/bin>rem                   command is executed. The default is "jdbconn".

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem $Id: catalina.bat,v 1.9.2.1 2004/08/21 15:49:47 yoavs Exp $


D:/Tomcat528/bin>rem -----------------------------------------------------------
----------------

D:/Tomcat528/bin>rem Guess CATALINA_HOME if not defined

D:/Tomcat528/bin>set CURRENT_DIR=D:/Tomcat528/bin

D:/Tomcat528/bin>if not "D:/Tomcat528" == "" goto gotHome

D:/Tomcat528/bin>if exist "D:/Tomcat528/bin/catalina.bat" goto okHome

D:/Tomcat528/bin>rem Get standard environment variables

D:/Tomcat528/bin>if exist "D:/Tomcat528/bin/setenv.bat" call "D:/Tomcat528/bin/s
etenv.bat"

D:/Tomcat528/bin>rem Get standard Java environment variables

D:/Tomcat528/bin>if exist "D:/Tomcat528/bin/setclasspath.bat" goto okSetclasspat
h

D:/Tomcat528/bin>set BASEDIR=D:/Tomcat528
//这里设置环境变量classpath 调用classpath.bat 
D:/Tomcat528/bin>call "D:/Tomcat528/bin/setclasspath.bat"

D:/Tomcat528/bin>rem -----------------------------------------------------------
----------------

D:/Tomcat528/bin>rem Set CLASSPATH and Java options

D:/Tomcat528/bin>rem

D:/Tomcat528/bin>rem $Id: setclasspath.bat,v 1.6.2.1 2004/08/21 15:49:50 yoavs E
xp $

D:/Tomcat528/bin>rem -----------------------------------------------------------
----------------

D:/Tomcat528/bin>rem Make sure prerequisite environment variables are set

D:/Tomcat528/bin>if not "D:/j2sdk1.4.2_06" == "" goto gotJavaHome

D:/Tomcat528/bin>if not exist "D:/j2sdk1.4.2_06/bin/java.exe" goto noJavaHome

D:/Tomcat528/bin>if not exist "D:/j2sdk1.4.2_06/bin/javaw.exe" goto noJavaHome

D:/Tomcat528/bin>if not exist "D:/j2sdk1.4.2_06/bin/jdb.exe" goto noJavaHome

D:/Tomcat528/bin>if not exist "D:/j2sdk1.4.2_06/bin/javac.exe" goto noJavaHome

D:/Tomcat528/bin>goto okJavaHome

D:/Tomcat528/bin>if not "D:/Tomcat528" == "" goto gotBasedir

D:/Tomcat528/bin>if exist "D:/Tomcat528/bin/setclasspath.bat" goto okBasedir

D:/Tomcat528/bin>rem Set the default -Djava.endorsed.dirs argument

D:/Tomcat528/bin>set JAVA_ENDORSED_DIRS=D:/Tomcat528/common/endorsed

D:/Tomcat528/bin>rem Set standard CLASSPATH

D:/Tomcat528/bin>rem Note that there are no quotes as we do not want to introduc
e random

D:/Tomcat528/bin>rem quotes into the CLASSPATH

D:/Tomcat528/bin>set CLASSPATH=D:/j2sdk1.4.2_06/lib/tools.jar

D:/Tomcat528/bin>rem Set standard command for invoking Java.

D:/Tomcat528/bin>rem Note that NT requires a window name argument when using sta
rt.

D:/Tomcat528/bin>rem Also note the quoting as JAVA_HOME may contain spaces.

D:/Tomcat528/bin>set _RUNJAVA="D:/j2sdk1.4.2_06/bin/java"

D:/Tomcat528/bin>set _RUNJAVAW="D:/j2sdk1.4.2_06/bin/javaw"

D:/Tomcat528/bin>set _RUNJDB="D:/j2sdk1.4.2_06/bin/jdb"

D:/Tomcat528/bin>set _RUNJAVAC="D:/j2sdk1.4.2_06/bin/javac"

D:/Tomcat528/bin>goto end

D:/Tomcat528/bin>rem Add on extra jar files to CLASSPATH

D:/Tomcat528/bin>if "" == "" goto noJsse

D:/Tomcat528/bin>set CLASSPATH=D:/j2sdk1.4.2_06/lib/tools.jar;D:/Tomcat528/bin/b
ootstrap.jar

D:/Tomcat528/bin>if not "d:/Tomcat528" == "" goto gotBase

D:/Tomcat528/bin>if not "" == "" goto gotTmpdir

D:/Tomcat528/bin>set CATALINA_TMPDIR=d:/Tomcat528/temp

D:/Tomcat528/bin>rem ----- Execute The Requested Command -----------------------
----------------

D:/Tomcat528/bin>echo Using CATALINA_BASE:   d:/Tomcat528
Using CATALINA_BASE:   d:/Tomcat528

D:/Tomcat528/bin>echo Using CATALINA_HOME:   D:/Tomcat528
Using CATALINA_HOME:   D:/Tomcat528

D:/Tomcat528/bin>echo Using CATALINA_TMPDIR: d:/Tomcat528/temp
Using CATALINA_TMPDIR: d:/Tomcat528/temp

D:/Tomcat528/bin>echo Using JAVA_HOME:       D:/j2sdk1.4.2_06
Using JAVA_HOME:       D:/j2sdk1.4.2_06

D:/Tomcat528/bin>set _EXECJAVA="D:/j2sdk1.4.2_06/bin/java"
//这里是程序的入口类马上就会关心它
D:/Tomcat528/bin>set MAINCLASS=org.apache.catalina.startup.Bootstrap

D:/Tomcat528/bin>set ACTION=start

D:/Tomcat528/bin>set SECURITY_POLICY_FILE=

D:/Tomcat528/bin>set DEBUG_OPTS=

D:/Tomcat528/bin>set JPDA=

D:/Tomcat528/bin>if not ""start"" == ""jpda"" goto noJpda

D:/Tomcat528/bin>if ""start"" == ""debug"" goto doDebug

D:/Tomcat528/bin>if ""start"" == ""run"" goto doRun

D:/Tomcat528/bin>if ""start"" == ""start"" goto doStart

D:/Tomcat528/bin>shift

D:/Tomcat528/bin>if not "Windows_NT" == "Windows_NT" goto noTitle

D:/Tomcat528/bin>set _EXECJAVA=start "Tomcat" "D:/j2sdk1.4.2_06/bin/java"

D:/Tomcat528/bin>goto gotTitle

D:/Tomcat528/bin>if not """" == ""-security"" goto execCmd

D:/Tomcat528/bin>rem Get remaining unshifted command line arguments and save the
m in the

D:/Tomcat528/bin>set CMD_LINE_ARGS=

D:/Tomcat528/bin>if """" == """" goto doneSetArgs

D:/Tomcat528/bin>rem Execute Java with the applicable properties

D:/Tomcat528/bin>if not "" == "" goto doJpda

D:/Tomcat528/bin>if not "" == "" goto doSecurity
执行java 命令带一些比较多的参数选项.
D:/Tomcat528/bin>start "Tomcat" "D:/j2sdk1.4.2_06/bin/java"    -Djava.endorsed.d
irs="D:/Tomcat528/common/endorsed" -classpath "D:/j2sdk1.4.2_06/lib/tools.jar;D:
/Tomcat528/bin/bootstrap.jar" -Dcatalina.base="d:/Tomcat528" -Dcatalina.home="D:
/Tomcat528" -Djava.io.tmpdir="d:/Tomcat528/temp" org.apache.catalina.startup.Boo
tstrap  start

D:/Tomcat528/bin>goto end
D:/Tomcat528/bin>
     

此时Tomcat已经启动
我们关心catalina.bat 做的关键动作.
call "%CATALINA_HOME%/bin/setclasspath.bat"  //设置classpath
set SECURITY_POLICY_FILE=%CATALINA_BASE%/conf/catalina.policy //指定安全策略管理文件

/*
 * 指定程序入口类.
 */
set _EXECJAVA=%_RUNJAVA%
set MAINCLASS=org.apache.catalina.startup.Bootstrap
set ACTION=start
set SECURITY_POLICY_FILE=
set DEBUG_OPTS=
set JPDA=

/*
 * 启动应用带设置好的各种参数
 */
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" 
-classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" 
-Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%










首先找到org.apache.catalina.startup  包下的Bootstrap文件。
先看main()  推进进行调试如此可以对程序流程有一个清晰的认识。

 /**
     * Main method, used for testing only.
     *
     * @param args Command line arguments to be processed
     */
    public static void main(String args[]) {

 /**
  *   加载JMX,我们先不理它:)
  */ 
        try {
            // Attempt to load JMX class
            new ObjectName("test:foo=bar");
        } catch (Throwable t) {
            System.out.println(JMX_ERROR_MESSAGE);
            try {
                // Give users some time to read the message before exiting
                Thread.sleep(5000);
            } catch (Exception ex) {
            }
            return;
        }
       /*
        *  /**
      * Daemon object used by main.
        * 该类声明了一个静态对象引用。
    * private static Bootstrap daemon = null;
        */
        if (daemon == null) {
            daemon = new Bootstrap();
            try {
                daemon.init();
            } catch (Throwable t) {
                t.printStackTrace();
                return;
            }
        }

        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            if (command.equals("startd")) {
                args[0] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd")) {
                args[0] = "stop";
                daemon.stop();
            } else if (command.equals("start")) {
                daemon.setAwait(true);
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stop")) {
                daemon.stopServer(args);
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }

    }
    
    
    查看init()方法 首先调用以下3个方法
      // Set Catalina path 设置catalina.home
        setCatalinaHome();
        //设置 setCatalinaBase
        setCatalinaBase();
        //建立3个ClassLoader
        initClassLoaders();
        {
         commonLoader = createClassLoader("common", null);
         catalinaLoader = createClassLoader("server", commonLoader);
         sharedLoader = createClassLoader("shared", commonLoader);
        }

什么是classLoader 查看javadoc 以下是1.4javadoc 的简介.
public abstract class ClassLoader
extends Object
A class loader is an object that is responsible for loading classes.
The class ClassLoader is an abstract class. Given the name of a class,
 a class loader should attempt to locate or generate data 
 that constitutes a definition for the class. 
 A typical strategy is to transform the name into a file name 
 and then read a "class file" of that name from a file system.
 
      现在,应用程序已经加载了需要的基本classes  jar包等。从一个配置文件catalina.home/conf/catalina.properties读取
  这是一种通用的技术,把需要的资源中固化的文件中读出来文件格式比较早的有*.ini unix/linux下的 *.profile
  以及java常用的*.properties.  和现在非常流行的 *.xml 等。如此我们可以把可能变化比较大的参数保存在
  配置文件中, 程序通过特定的api 读取。如数据库连接参数等。 不再多说这是一种常见而实用的技术。 
  有兴趣可以看一下hibernate加载数据库连接的源码, struts, spring等初始化代码。
  
  加载的文件
  common.loader=${catalina.home}/common/classes,${catalina.home}/common/endorsed/*.jar,${catalina.home}/common/lib/*.jar
  
  server.loader=${catalina.home}/server/classes,${catalina.home}/server/lib/*.jar
  
  shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar
  
      接下来init()执行了以下语句
      
      Class startupClass =
            catalinaLoader.loadClass
            ("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.newInstance();

        // Set the shared extensions class loader
        if (debug >= 1)
            log("Setting startup class properties");
        String methodName = "setParentClassLoader";
        Class paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramvalues[] = new Object[1];
        paramvalues[0] = sharedLoader;
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramvalues);

        catalinaDaemon = startupInstance;
        
        现在你需要看一下java的反射机制, 否则很难读懂这部分代码, 简单的说java的反射技术提供
        了一种类的自检[c++中可没有这种技术:)] 它能给出这个类的几乎全部信息如数据成员,方法的参数列表
        返回类型等。
        
        //创建了一个Catalina对象.
        Object startupInstance = startupClass.newInstance();
        // 相当于调用 startupInstance.setParentClassLoader(java.lang.ClassLoader);
        method.invoke(startupInstance, paramvalues);
        
        注意tomcat5.0.2.8 的启动代码与tomcat4.x.x.x 有所区别。
        4.x版本这时直接调用了startupInstance.process()方法。而这里还有一些其他处理。
        
        
        由于我们没有输入命令行参数。 直接startup....  程序进入
        else if (command.equals("start")) {
                //运用反射相当于上调用了catalinaDaemon.setAwait(true);
                daemon.setAwait(true);
               //运用反射相当于上调用了catalinaDaemon.load("start");
                daemon.load(args);
                //运用反射相当于上调用了catalinaDaemon.start();
                daemon.start();
                
       
       到这里不能不提一下Catalina的 public void load() 方法
       public void load() {
       
        //设置目录
        initDirs();

        // Before digester - it may be needed
 //看了一眼不大清楚什么意思,放一放
 // 心急的人可以去查一下文档 基本上是说tomcat作为嵌入式应用的时候使用
 //  http://jakarta.apache.org/tomcat/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/startup/Embedded.html
        initNaming();

        // Create and execute our Digester
     

        
        Digester digester = createStartDigester();
        //记录时间, 还记得Tomcat启动后显示一个 用了多少ms 时间吧.  例  信息: Server startup in 19337 ms
        long t1 = System.currentTimeMillis();

        Exception ex = null;
        InputSource inputSource = null;
        InputStream inputStream = null;
        try {
            File file = configFile();
            inputStream = new FileInputStream(file);
            inputSource = new InputSource("file&://" + file.getAbsolutePath());
        } catch (Exception e) {
            ;
        }
        if (inputStream == null) {
            try {
                inputStream = getClass().getClassLoader()
                    .getResourceAsStream(getConfigFile());
                inputSource = new InputSource
                    (getClass().getClassLoader()
                     .getResource(getConfigFile()).toString());
            } catch (Exception e) {
                ;
            }
        }

        if (inputStream == null) {
            System.out.println("Can't load server.xml");
            return;
        }

        try {
            inputSource.setByteStream(inputStream);
            digester.push(this);
            digester.parse(inputSource);
            inputStream.close();
        } catch (Exception e) {
            System.out.println("Catalina.start using "
                               + getConfigFile() + ": " + e);
            e.printStackTrace(System.out);
            return;
        }

        // Replace System.out and System.err with a custom PrintStream
        // TODO: move to Embedded, make it configurable
        SystemLogHandler systemlog = new SystemLogHandler(System.out);
        System.setOut(systemlog);
        System.setErr(systemlog);

        // Start the new server
        if (server instanceof Lifecycle) {
            try {
                server.initialize();
            } catch (LifecycleException e) {
                log.error("Catalina.start", e);
            }
        }

        long t2 = System.currentTimeMillis();
        log.info("Initialization processed in " + (t2 - t1) + " ms");

    }

       /*
 *  我不喜欢提太多的设计模式, 我们作为一种使用方案的思路来理解就可以了。
 *  Digester模式参考 http://www.uml.org.cn/rjjg/rjjg28.htm
 *  
 * createStartDigester()方法创建了装载Tomcat核心组件资源规则。我们现在需要知道Tomcat5.x采用的是面向
 * 组件的软件技术,似乎它是比面向对象更加深奥,不过没什么神秘的, 如果你们工科出身你大可以理解为
 * 一个系统,比如一个车床,如很多系统组成,如动力系统,控制系统,物料循环系统,每个系统根据约定的
 * 工程标准负责自己的工作,并且每个零件系统可以由不同的厂家生产。 如果软件工程能达到这种程度当然是
 * 几乎完美的,遗憾的是软件产业还是一门新兴产业,它要学习其他工业的地方还很多。从技术和经验上都还有很多
 * 欠缺,不过面向组件的编程技术,毫无疑问是一个值得我们研究的方面。(忍不住说了点废话--_--)
 * 
 * 让我们看看这一大堆代码干了些什么。这里用到了规则集打包技术。即将相关同类型规则都放在一个类中,
 * 此由这些规则被装载然后被注册使用。我们大概可以猜到这些怪异的代码似乎创建了以下对象,
 * 如Server/Service/Engine/Host/Context/    这就是tomcat的核心组件。以后的日记里我们将逐个介绍。
 * 
 */
 
 我们看一下Digester解析的文件。conf目录下的server.xml
 现在我们明白了刚才发生了什么.根据server.xml文件,程序已经加载了server.xml定义的所有对象,
 并且已经把程序里定义的相关类的属性值赋值给创建的对象。
 例如:<Server port="8005" shutdown="SHUTDOWN" debug="0"> 
 结果创建了一个类型为  org.apache.catalina.core.StandardServer的对象,属性port=8005
 shutdown="SHUTDOWN" debug=0
 不可思议, 确实不错,感叹一下,汗。。。。。。。。:)
 
 经过了无数次检查,,读取配置文件的操作后,我们终于加载了应用程序需要的资源,同时执行了这些对象
 需要进行的初始化方法。 
 终于执行到了start()
 
  /**
     * Start a new server instance.
     */
    public void start() {

        if (server == null) {
            load();
        }

        long t1 = System.currentTimeMillis();

        // Start the new server
        if (server instanceof Lifecycle) {
            try {
                ((Lifecycle) server).start();
            } catch (LifecycleException e) {
                log.error("Catalina.start: ", e);
            }
        }

        long t2 = System.currentTimeMillis();
        log.info("Server startup in " + (t2 - t1) + " ms");

        try {
            //创建一个钩子,当输入shutdown时关闭应用程序。
            // Register shutdown hook
            if (useShutdownHook) {
                if (shutdownHook == null) {
                    shutdownHook = new CatalinaShutdownHook();
                }
                Runtime.getRuntime().addShutdownHook(shutdownHook);
            }
        } catch (Throwable t) {
            // This will fail on JDK 1.2. Ignoring, as Tomcat can run
            // fine without the shutdown hook.
        }

        if (await) {
            await();
            stop();
        }

    }   我看到了一个LIfecycle接口,估计是管理生命周期的,毫无疑问非常重要, 这里调用了
    org.apache.catalina.core.StandardServer 的start()方法。
    该方法循环调用了, 所有services[i]对象的start()方法。
    接着调用了org.apache.catalina.core.StandardServiece的start方法
        if (container != null) {
            synchronized (container) {
                if (container instanceof Lifecycle) {
                    ((Lifecycle) container).start();
                }
            }
        }
        //依次调用了一个或多个Server/Service/Engine/Host/Context/对象的start().....应用程序启动完毕。
        
        ok 写到这里,我觉得有点累了, 粗略的读了一下tomcat启动相关代码。 只能说知其然,而不知其
        所以然。但是程序的思路清晰而明确,将复杂的应用规划的井井有条。 不能不说是一个优秀的设计。
        
        
        总结一下, 我们大概知道了再我们输入startup后发生什么事情, 对tomcat启动过程有了一个感性的认识。
        
        
        估计,我们大家都承认一本好书, 读一遍是远远不够的,同样代码也需要读个2-3次吧
         这里分析的只是写代码的皮毛耳, 要想体会到程序设计思路, 我们还需要相当大的努力,
         不过无论如何,我们已经走出了第一步。
        
        
        
        
        
        由于个人水平有限,几乎难免有不当甚至错误之处。请大家谅解。
        抛砖引玉,期待大家的精彩文章。
        
        
        Looking forwards:  下一篇里,将对org.apache.catalina.core包的一些类做一定的介绍。
        同时, 我们需要补充一些servlet技术框架. http协议的相关知识。 
        
                                                            see u guys next week ! Good luck!
                                                            
                                                            
                                                            by jinchen 2005-3-4
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值