How Tomcat Work 之 第十七章:Tomcat Startup

来源:互联网 发布:聚丙烯看盘软件下载 编辑:程序博客网 时间:2024/06/02 20:20



回顾


这章主要讲Tomcat的启动,使用到两个类分别是:Catalina和Bootstrap。Catalina类用于启动和停止一个服务器对象也解析Tomcat的配置文件,server.xml。Bootstrap类用于创建Catalina实例并调用其处理方法。理论上,这两个类已经合并了。然而,为支持更多的模式运行Tomcat,提供了大量的Bootstrap类。例如,上面提及的Bootstrap类用于单独的应用运行Tomcat。另一个类,BootstrapService,作为Windows NT Service来运行Tomcat。


为了用户方便,Tomcat也提供批量文件和shell脚本来开启和停止容器。在这些批量文件和shell脚本的帮助下,用户不需要去记java.exe程序的选项来运行Bootstrap类。而选择运行适量的批量文件或者shell脚本。


这章的第一部分讨论了Catalina类,第二部分讨论了Bootstrap类。只有认真理解了第十四章的server和Service,第十五章的Digester,第十六章的shutdown hooks,才能很好地理解本章的内容。这章也讨论了如何在windows/linux上运行Tomcat。一部分致力于批量文件启动和停止Window的Tomcat。另一部分讲述了Unix/Linux的shell脚本。


The Catalian class


org.apache.catalina.startup.Catalina类是一个启动类。它包含了一个Digester来解析%CATALINE_HOME%/conf目录下的server.xml文件。理解了添加到这个Digester的规则,你可以根据你所想的来配置你的Tomcat。


Catalian类也封装了一个Server对象,其有一个Service。就如第十五章中提到的,一个Service对象包含了一个容器和一个或者更多的连接器。你使用Catalian启动和停止这个服务器对象。


实例化这个Catalian类来运行Tomcat并稍后调用其处理方法。当调用这个方法的时候必须传递合适的参数。如果你想启动Tomcat,第一个参数是start,如果想发送一个shutdown命令来停止 参数就是stop。也有其他可接受的参数,比如-help,-config,-debug,和-nonaming。


注意:ninaming参数,如果存在,指定JNDI命名是不应该支持的。查看org.apache.naming包获取更多的信息关于JNDI命名如何支持Tomcat。


一般地,你需要一个Bootstrap类来实例化Catalian并调用其处理方法,即使Catalian类有一个main方法提供了一个入口点。Bootstap类其中一个在下一节中讲述。你也将在这一节中知道Bootstarp做了什么。


Tomcat 4中的Catalian的处理方法的代码清单如下:


public void process(String args[]) {    setCatalinaHome();    setCatalinaBase();    try {        if (arguments(args))            execute();    }    catch (Exception e) {        e.printStackTrace(System.out);    }}



process方法设置了两个系统属性,catalina.home和catalian.base.catalina.home,其是user.dir属性的默认值。catalina.base属性指定为catalina.home的值。因此,两个属性有usr.dir属性的值。


注意,urer.dir系统属性涉及到用户的工作目录,即,调用Java命令的目录。为查看系统属性列表,查看java.lang.System的getProperties方法。


process方法之后调用arguments方法,传递参数列表。arguments方法,代码清单17.2如下,处理命令行参数,如果catalina对象应该继续执行返回true。


protected boolean arguments(String args[]) {    boolean isConfig = false;    if (args.length < 1) {        usage();        return (false);    }        for (int i = 0; i < args.length; i++) {       if (isConfig) {           configFile = args[i];           isConfig = false;       }       else if (args[i].equals("-config")) {           isConfig = true;       }       else if (args[i].equals("-debug")) {           debug = true;       }       else if (args[i].equals("-nonaming")) {           useNaming = false;       }       else if (args[i].equals("-help")) {           usage();           return (false);       }       else if (args[i].equals("start")) {           starting = true;       }       else if (args[i].equals("stop")) {          stopping = true;       }       else {           usage();           return (false);       }    }    return (true);} 


process方法演示了arguments方法的返回值并且如果arguments方法返回true调用execute方法。此方法的代码清单17.3如下:


protected void execute() throws Exception {    if (starting)       start();   else if (stopping)       stop();}


execute方法要不调用start方法启动Tomcat,要不调用stop方法停止Tomcat。这两个方法在下一节中讨论。


注意:在Tomcat 5中,不再有execute方法。start或者stop方法由process方法直接调用。


The start Method


start方法创建了一个Digester实例来处理server.xml方法(Tomcat的配置文件)。在解析XML文件之前,start方法调用Digester的push方法,来解析当前Catalian对象。这样Catalian对象将是Digester内部对象栈中的第一个对象。parsing 将导致一个Server变量引用一个Server对象,默认地是org.apache.catalian.core.StandardServer类型。start方法将稍后调用Server对象的intialize方法和start方法。Catalian的start方法稍后继续通过调用Server对象的await方法,导致Server对象来指定一个线程来等待一个shutdown命令。await方法不会返回直到接受到一个关闭命令。当await方法返回的时候,Catalina的start方法调用服务器对象的stop方法,将停止服务器对象和所有其他的组件。start方法也将布置一个shutdown 钩子确保用户突然退出的时候,服务器对象的stop方法理应执行。


start方法的代码清单如下:


protected void start() {   // Create and execute our Digester   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);     }     // Setting additional variables     if (!useNaming) {         System.setProperty("catalina.useNaming", "false");     }     else {         System.setProperty("catalina.useNaming", "true");         String value = "org.apache.naming";         String oldValue =System.getProperty(javax.naming.Context.URL_PKG_PREFIXES);         if (oldValue != null) {             value = value + ":" + oldValue;          }          System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, value);          value = System.getProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY);          if (value == null) {              System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,"org.apache.naming.java.javaURLContextFactory");          }      }      // If a SecurityManager is being used, set properties for       // checkPackageAccess() and checkPackageDefinition      if( System.getSecurityManager() != null ) {          String access = Security.getProperty("package.access");          if( access != null && access.length() > 0 )              access += ",";          else              access = "sun.,";          Security.setProperty("package.access",access + "org.apache.catalina.,org.apache.jasper.");          String definition = Security.getProperty("package.definition");          if( definition != null && definition.length() > 0 )               definition += ",";          else              definition = "sun.,";          Security.setProperty("package.definition",definition + "java.,org.apache.catalina.,org.apache.jasper.");        }        // Replace System.out and System.err with a custom PrintStream       SystemLogHandler log = new SystemLogHandler(System.out);       System.setOut(log);       System.setErr(log);             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) {              System.out.println("Catalina.start: " + e);              e.printStackTrace(System.out);              if (e.getThrowable() != null) {                  System.out.println("----- Root Cause -----");                  e.getThrowable().printStackTrace(System.out);              }           }        }        // Shut down the server        if (server instanceof Lifecycle) {            try {                try {                    // Remove the ShutdownHook first so that server.stop()                    // doesn't get invoked twice                    Runtime.getRuntime().removeShutdownHook(shutdownHook);          }          catch (Throwable t) {              // This will fail on JDK 1.2. Ignoring, as Tomcat can run              // fine without the shutdown hook.          }          ((Lifecycle) server).stop();     }          catch (LifecycleException e) {         System.out.println("Catalina.stop: " + e);         e.printStackTrace(System.out);         if (e.getThrowable() != null) {             System.out.println("----- Root Cause -----");             e.getThrowable().printStackTrace(System.out);         }     }   }}  



The stop Method


stop方法停止Catalina和导致Server对象关闭。代码清单如下:


protected void stop() {    // Create and execute our Digester    Digester digester = createStopDigester();    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.stop: " + e);         e.printStackTrace(System.out);         System.exit(1);      }      // Stop the existing server      try {          Socket socket = new Socket("127.0.0.1", server.getPort());          OutputStream stream = socket.getoutputStream();          String shutdown = server.getShutdown();          for (int i = 0; i < shutdown.length(); i++)            stream.write(shutdown.charAt(i));            stream.flush();            stream.close();            socket.close();      }      catch (IOException e) {            System.out.println("Catalina.stop: " + e);            e.printStackTrace(System.out);            System.exit(1);      }}        



注意:stop方法调用createStopDigester方法创建了一个Digester实例,通过调用Digester的push方法将当前Catalina对象放入Digester的内部栈中并解析配置文件。关于添加到Digester的规则在“Stop Digester”章节中讨论。


stop方法发送一条关闭命令来停止运行的服务器对象。




0 0
原创粉丝点击