How Tomcat Works(十九)

系统 1769 0

本文重点关注启动tomcat时会用到的两个类,分别为Catalina类和Bootstrap类,它们都位于org.apachae.catalina.startup包下;Catalina类用于启动或关闭Server对象,并负责解析server.xml配置文件;Bootstrap类是一个入口点,负责创建Catalina实例,并调用其process()方法。

org.apachae.catalina.startup.Catalina类是启动类,它包含一个Digester对象,用于解析位于%CATALINE_HOME%/conf目录的server.xml文件

Catalina类还封装了一个Server对象,该对象持有一个Service对象(Service对象包含一个Servlet容器和一个或多个连接器)。可以使用Catalina类来启动/关闭Server对象

可以通过实例化Catalina类,并调用其process()方法来运行Tomcat,但在调用该方法时,需要传入适当的参数(如start或stop -help -config -debug -nonaming等)。

      
        /**
      
      
        
     * The instance main program.
     *
     * 
      
      
        @param
      
      
         args Command line arguments
     
      
      
        */
      
      
        public
      
      
        void
      
      
         process(String args[]) {

        setCatalinaHome();
        setCatalinaBase();
        
      
      
        try
      
      
         {
            
      
      
        if
      
      
         (arguments(args))
                execute();
        } 
      
      
        catch
      
      
         (Exception e) {
            e.printStackTrace(System.out);
        }
    }
      
    

上面方法会进一步调用execute()方法,execute()方法会根据传入参数调用start()方法或stop()方法

start方法会创建一个Digester对象来解析server.xml文件(Tomcat配置文件)。在解析server.xml文件之前,start方法会调用Digester对象的push方法,传入当前的Catalina对象为参数。这样,Catalina对象就成了Digester对象内部对象栈的第一个对象。解析server.xml文件后,会将变量server指向一个Server对象(默认是org.apache.catalina.core.StandardServer类型的对象)。然后,start方法会调用server的initialize和start方法。Catalina对象的start方法会调用Server对象的await方法,server对象会使用一个专用的线程来等待关闭命令。await方法会循环等待,知道接收到正确的关闭命令。当await方法返回时,Catalina对象的start方法会调用server对象的stop方法,从而关闭server对象和其他的组件。此外,start方法还会注册shutdown hook,确保服务器关闭时会执行Server对象的stop方法。

start方法的实现如下:

      
        /**
      
      
        
     * Start a new server instance.
     
      
      
        */
      
      
        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"
      
        ,
                
      
      
        //
      
      
         FIX ME package "javax." was removed to prevent HotSpot
                
      
      
        //
      
      
         fatal internal errors
      
      
                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);
                }
            }
        }

    }
      
    

其中的CatalinaShutdownHook类为关闭钩子

      
        /**
      
      
        
     * Shutdown hook which will perform a clean shutdown of Catalina if needed.
     
      
      
        */
      
      
        protected
      
      
        class
      
       CatalinaShutdownHook 
      
        extends
      
      
         Thread {

        
      
      
        public
      
      
        void
      
      
         run() {

            
      
      
        if
      
       (server != 
      
        null
      
      
        ) {
                
      
      
        try
      
      
         {
                    ((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);
                    }
                }
            }

        }
    }
      
    

Catalina对象的stop方法会关闭Server对象,其实现如下:

      
        /**
      
      
        
     * Stop an existing server instance.
     
      
      
        */
      
      
        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对象,然后将Catalina对象push到Digester对象的内部对象栈中。

createStartDigester方法创建了一个Digester对象,然后将规则添加到其中,解析server.xml文件。添加到Digester对象中的规则是理解tomcat配置的关键。

createStartDigester方法的实现如下:

      
        /**
      
      
        
     * Create and configure the Digester we will be using for startup.
     
      
      
        */
      
      
        protected
      
      
         Digester createStartDigester() {

        
      
      
        //
      
      
         Initialize the digester
      
      
        Digester digester = 
      
        new
      
      
         Digester();
        
      
      
        if
      
      
         (debug)
            digester.setDebug(
      
      999
      
        );
        digester.setValidating(
      
      
        false
      
      
        );

        
      
      
        //
      
      
         Configure the actions we will be using
      
      
        digester.addObjectCreate("Server"
      
        ,
                                 
      
      "org.apache.catalina.core.StandardServer"
      
        ,
                                 
      
      "className"
      
        );
        digester.addSetProperties(
      
      "Server"
      
        );
        
        
          digester.addSetNext(
        
      
      
        "Server",
                            "setServer",
                            "org.apache.catalina.Server"
      
      
        
          );
        
        

        digester.addObjectCreate(
      
      "Server/GlobalNamingResources"
      
        ,
                                 
      
      "org.apache.catalina.deploy.NamingResources"
      
        );
        digester.addSetProperties(
      
      "Server/GlobalNamingResources"
      
        );
        digester.addSetNext(
      
      "Server/GlobalNamingResources"
      
        ,
                            
      
      "setGlobalNamingResources"
      
        ,
                            
      
      "org.apache.catalina.deploy.NamingResources"
      
        );

        digester.addObjectCreate(
      
      "Server/Listener"
      
        ,
                                 
      
      
        null
      
      , 
      
        //
      
      
         MUST be specified in the element
      
      
                                 "className"
      
        );
        digester.addSetProperties(
      
      "Server/Listener"
      
        );
        digester.addSetNext(
      
      "Server/Listener"
      
        ,
                            
      
      "addLifecycleListener"
      
        ,
                            
      
      "org.apache.catalina.LifecycleListener"
      
        );

        digester.addObjectCreate(
      
      "Server/Service"
      
        ,
                                 
      
      "org.apache.catalina.core.StandardService"
      
        ,
                                 
      
      "className"
      
        );
        digester.addSetProperties(
      
      "Server/Service"
      
        );
        digester.addSetNext(
      
      "Server/Service"
      
        ,
                            
      
      "addService"
      
        ,
                            
      
      "org.apache.catalina.Service"
      
        );

        digester.addObjectCreate(
      
      "Server/Service/Listener"
      
        ,
                                 
      
      
        null
      
      , 
      
        //
      
      
         MUST be specified in the element
      
      
                                 "className"
      
        );
        digester.addSetProperties(
      
      "Server/Service/Listener"
      
        );
        digester.addSetNext(
      
      "Server/Service/Listener"
      
        ,
                            
      
      "addLifecycleListener"
      
        ,
                            
      
      "org.apache.catalina.LifecycleListener"
      
        );

        digester.addObjectCreate(
      
      "Server/Service/Connector"
      
        ,
                                 
      
      "org.apache.catalina.connector.http.HttpConnector"
      
        ,
                                 
      
      "className"
      
        );
        digester.addSetProperties(
      
      "Server/Service/Connector"
      
        );
        digester.addSetNext(
      
      "Server/Service/Connector"
      
        ,
                            
      
      "addConnector"
      
        ,
                            
      
      "org.apache.catalina.Connector"
      
        );

        digester.addObjectCreate(
      
      "Server/Service/Connector/Factory"
      
        ,
                                 
      
      "org.apache.catalina.net.DefaultServerSocketFactory"
      
        ,
                                 
      
      "className"
      
        );
        digester.addSetProperties(
      
      "Server/Service/Connector/Factory"
      
        );
        digester.addSetNext(
      
      "Server/Service/Connector/Factory"
      
        ,
                            
      
      "setFactory"
      
        ,
                            
      
      "org.apache.catalina.net.ServerSocketFactory"
      
        );

        digester.addObjectCreate(
      
      "Server/Service/Connector/Listener"
      
        ,
                                 
      
      
        null
      
      , 
      
        //
      
      
         MUST be specified in the element
      
      
                                 "className"
      
        );
        digester.addSetProperties(
      
      "Server/Service/Connector/Listener"
      
        );
        digester.addSetNext(
      
      "Server/Service/Connector/Listener"
      
        ,
                            
      
      "addLifecycleListener"
      
        ,
                            
      
      "org.apache.catalina.LifecycleListener"
      
        );

        
      
      
        //
      
      
         Add RuleSets for nested elements
      
      
        digester.addRuleSet(
      
        new
      
       NamingRuleSet("Server/GlobalNamingResources/"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       EngineRuleSet("Server/Service/"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       HostRuleSet("Server/Service/Engine/"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       ContextRuleSet("Server/Service/Engine/Default"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       NamingRuleSet("Server/Service/Engine/DefaultContext/"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       ContextRuleSet("Server/Service/Engine/Host/Default"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       NamingRuleSet("Server/Service/Engine/Host/DefaultContext/"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       ContextRuleSet("Server/Service/Engine/Host/"
      
        ));
        digester.addRuleSet(
      
      
        new
      
       NamingRuleSet("Server/Service/Engine/Host/Context/"
      
        ));

        digester.addRule(
      
      "Server/Service/Engine"
      
        ,
                         
      
      
        new
      
      
         SetParentClassLoaderRule(digester,
                                                      parentClassLoader));


        
      
      
        return
      
      
         (digester);

    }
      
    

这里需要注意的是 digester.addSetNext("Server", "setServer","org.apache.catalina.Server")方法,该方法将Server对象压入到Digester对象的内部栈中,并与栈中的下一个对象相关联;在这里,下一个对象是Catalina实例,调用其setServer()方法与Server对象相关联。

createStopDigester方法返回一个Digester对象来关闭Server对象。createStopDigester方法实现如下:

      
        /**
      
      
        
     * Create and configure the Digester we will be using for shutdown.
     
      
      
        */
      
      
        protected
      
      
         Digester createStopDigester() {

        
      
      
        //
      
      
         Initialize the digester
      
      
        Digester digester = 
      
        new
      
      
         Digester();
        
      
      
        if
      
      
         (debug)
            digester.setDebug(
      
      999
      
        );

        
      
      
        //
      
      
         Configure the rules we need for shutting down
      
      
        digester.addObjectCreate("Server"
      
        ,
                                 
      
      "org.apache.catalina.core.StandardServer"
      
        ,
                                 
      
      "className"
      
        );
        digester.addSetProperties(
      
      "Server"
      
        );
       
        
           digester.addSetNext(
        
      
      
        "Server",
                            "setServer",
                            "org.apache.catalina.Server");

        
      
      
        return
      
      
         (digester);

    }
      
    

与启动Digester对象不同,关闭Digester对象只对XML文件的根元素感兴趣

 org.apache.catalina.startup.Bootstrap类提供了启动tomcat的切入点(还有一些其他的类也有此功能)。当使用bat或sh启动tomcat时,实际上会调用该类的main方法。在main方法中会创建三个loader,并实例化Catalina对象,然后调用Catalina对象的process方法。

Bootstrap类的定义如下所示:

      
        public
      
      
        final
      
      
        class
      
      
         Bootstrap {


    
      
      
        //
      
      
         ------------------------------------------------------- Static Variables
      
      
        /**
      
      
        
     * Debugging detail level for processing the startup.
     
      
      
        */
      
      
        private
      
      
        static
      
      
        int
      
       debug = 0
      
        ;


    
      
      
        //
      
      
         ----------------------------------------------------------- Main Program
      
      
        /**
      
      
        
     * The main program for the bootstrap.
     *
     * 
      
      
        @param
      
      
         args Command line arguments to be processed
     
      
      
        */
      
      
        public
      
      
        static
      
      
        void
      
      
         main(String args[]) {

        
      
      
        //
      
      
         Set the debug flag appropriately
      
      
        for
      
       (
      
        int
      
       i = 0; i < args.length; i++
      
        )  {
            
      
      
        if
      
       ("-debug"
      
        .equals(args[i]))
                debug 
      
      = 1
      
        ;
        }
        
        
      
      
        //
      
      
         Configure catalina.base from catalina.home if not yet set
      
      
        if
      
       (System.getProperty("catalina.base") == 
      
        null
      
      
        )
            System.setProperty(
      
      "catalina.base"
      
        , getCatalinaHome());

        
      
      
        //
      
      
         Construct the class loaders we will need
      
      
        ClassLoader commonLoader = 
      
        null
      
      
        ;
        ClassLoader catalinaLoader 
      
      = 
      
        null
      
      
        ;
        ClassLoader sharedLoader 
      
      = 
      
        null
      
      
        ;
        
      
      
        try
      
      
         {

            File unpacked[] 
      
      = 
      
        new
      
       File[1
      
        ];
            File packed[] 
      
      = 
      
        new
      
       File[1
      
        ];
            File packed2[] 
      
      = 
      
        new
      
       File[2
      
        ];
            ClassLoaderFactory.setDebug(debug);

            unpacked[
      
      0] = 
      
        new
      
      
         File(getCatalinaHome(),
                                   
      
      "common" + File.separator + "classes"
      
        );
            packed2[
      
      0] = 
      
        new
      
      
         File(getCatalinaHome(),
                                  
      
      "common" + File.separator + "endorsed"
      
        );
            packed2[
      
      1] = 
      
        new
      
      
         File(getCatalinaHome(),
                                  
      
      "common" + File.separator + "lib"
      
        );
            commonLoader 
      
      =
      
        
                ClassLoaderFactory.createClassLoader(unpacked, packed2, 
      
      
        null
      
      
        );

            unpacked[
      
      0] = 
      
        new
      
      
         File(getCatalinaHome(),
                                   
      
      "server" + File.separator + "classes"
      
        );
            packed[
      
      0] = 
      
        new
      
      
         File(getCatalinaHome(),
                                 
      
      "server" + File.separator + "lib"
      
        );
            catalinaLoader 
      
      =
      
        
                ClassLoaderFactory.createClassLoader(unpacked, packed,
                                                     commonLoader);

            unpacked[
      
      0] = 
      
        new
      
      
         File(getCatalinaBase(),
                                   
      
      "shared" + File.separator + "classes"
      
        );
            packed[
      
      0] = 
      
        new
      
      
         File(getCatalinaBase(),
                                 
      
      "shared" + File.separator + "lib"
      
        );
            sharedLoader 
      
      =
      
        
                ClassLoaderFactory.createClassLoader(unpacked, packed,
                                                     commonLoader);
        } 
      
      
        catch
      
      
         (Throwable t) {

            log(
      
      "Class loader creation threw exception"
      
        , t);
            System.exit(
      
      1
      
        );

        }

        Thread.currentThread().setContextClassLoader(catalinaLoader);

        
      
      
        //
      
      
         Load our startup class and call its process() method
      
      
        try
      
      
         {

            SecurityClassLoad.securityClassLoad(catalinaLoader);

            
      
      
        //
      
      
         Instantiate a startup class instance
      
      
        if
      
       (debug >= 1
      
        )
                log(
      
      "Loading startup class"
      
        );
            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);

            
      
      
        //
      
      
         Call the process() method
      
      
        if
      
       (debug >= 1
      
        )
                log(
      
      "Calling startup class process() method"
      
        );
            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);

        } 
      
      
        catch
      
      
         (Exception e) {
            System.out.println(
      
      "Exception during startup processing"
      
        );
            e.printStackTrace(System.out);
            System.exit(
      
      2
      
        );
        }

    }


    
      
      
        /**
      
      
        
     * Get the value of the catalina.home environment variable.
     
      
      
        */
      
      
        private
      
      
        static
      
      
         String getCatalinaHome() {
        
      
      
        return
      
       System.getProperty("catalina.home"
      
        ,
                                  System.getProperty(
      
      "user.dir"
      
        ));
    }


    
      
      
        /**
      
      
        
     * Get the value of the catalina.base environment variable.
     
      
      
        */
      
      
        private
      
      
        static
      
      
         String getCatalinaBase() {
        
      
      
        return
      
       System.getProperty("catalina.base"
      
        , getCatalinaHome());
    }


    
      
      
        /**
      
      
        
     * Log a debugging detail message.
     *
     * 
      
      
        @param
      
      
         message The message to be logged
     
      
      
        */
      
      
        private
      
      
        static
      
      
        void
      
      
         log(String message) {

        System.out.print(
      
      "Bootstrap: "
      
        );
        System.out.println(message);

    }


    
      
      
        /**
      
      
        
     * Log a debugging detail message with an exception.
     *
     * 
      
      
        @param
      
      
         message The message to be logged
     * 
      
      
        @param
      
      
         exception The exception to be logged
     
      
      
        */
      
      
        private
      
      
        static
      
      
        void
      
      
         log(String message, Throwable exception) {

        log(message);
        exception.printStackTrace(System.out);

    }


}
      
    

Bootstrap类定义了四个静态方法,其中getCatalinaHome返回catalina.home属性的值,若没有,则返回user.dir属性的值。getCatalinaBase方法与getCatalinaHome方法类似。

Bootstrap类的main方法构造了三个loader,之所以如此做是为了防止运行WEB-INF/classes和WEB-INF/lib目录外的类。

其中commonLoader允许从%CATALINA_HOME%/common/classes,%CATALINA_HOME%/common/endorsed和%CATALINA_HOME%/common/lib目录下载入类。

catalinaLoader负责载入servlet容器需要使用的类,它只会从%CATALINA_HOME%/server/classes和%CATALINA_HOME%/server/lib目录下查找。

sharedLoader会从%CATALINA_HOME%/shared/classes和%CATALJNA_HOME%/shared/lib目录,以及对commonLoader可用的目录下查找需要的类。

然后,将sharedLoader设置为每个web应用的类载入器的父类载入器。(注意,sharedLoader并不访问catalina的内部类,或CLASSPATH中的类)

在创建了三个loader之后,main方法会载入Catalina类,实例化,并将之赋值给startupInstance变量。然后调用setParentClassLoader方法。

最后,main方法调用Catalina对象的process对象。

--------------------------------------------------------------------------- 

本系列How Tomcat Works系本人原创 

转载请注明出处 博客园 刺猬的温驯 

本人邮箱:   chenying998179 # 163.com ( #改为@

本文链接 http://www.cnblogs.com/chenying99/p/3250907.html

How Tomcat Works(十九)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论