How Tomcat Works(二十)

系统 1914 0

    要使用一个web应用程序,必须要将表示该应用程序的Context实例部署到一个host实例中。在tomcat中,context实例可以用war文件的形式来部署,也可以将整个web应用拷贝到Tomcat安装目录下的webapp下。对于部署的每个web应用程序,可以在其中包含一个描述文件(该文件是可选的),该文件中包含了对context的配置选项,是xml格式的文件。
注意,tomcat4和tomcat5使用两个应用程序来管理tomcat及其应用的部署,分别是manager应用程序和admin应用程序。这里两个应用程序位于%CATALINA_HOME%/server/webapps目录下,各自有一个描述文件,分别是manager.xml和admin.xml。
    本文将讨论使用一个部署器来部署web应用程序,部署器是org.apache.catalina.Deployer接口的实例。部署器需要与一个host实例相关联,用于部署context实例。部署一个context到host,即创建一个StandardContext实例,并将该context实例添加到host实例中。创建的context实例会随其父容器——host实例而启动(容器的实例在启动时总是会调用其子容器的start方法,除非该该container是一个wrapper实例)。
    本文会先说明tomcat部署器如何部署一个web应用程序,然后描述Deployer接口及其标准实现org.apache.catalina.core.StandardHostDeployer类的工作原理。

tomcat中在StandardHost中使用了一个生命周期监听器(lifecycle listener)org.apache.catalina.startup.HostConfig来部署应用。
当调用StandardHost实例的start方法时,会触发START事件,HostConfig实例会响应该事件,调用其start方法,在该方法中会部署并安装指定目录中的所有的web应用程序。

How Tomcat Works(十八) 中,描述了如何使用Digester对象来解析XML文档的内容,但并没有涉及Digester对象中所有的规则,其中被忽略掉的一个主题就是部署器,也就是本文的主题

在Tomcat中,org.apache.catalina.startup.Catalina类是启动类,使用Digester对象来解析server.xml文件,将其中的xml元素转换为java对象。

Catalina类中定义了createStartDigester方法来添加规则到Digester中:

      digester.addRuleSet(
      
        new
      
       HostRuleSet("Server/Service/Engine/"));
    

org.apache.catalina.startup.HostRuleSet类继承自org.apache.commons.digester.RuleSetBase类,作为RuleSetBase的子类,HostRuleSet提供了addRuleInstances方法实现,该方法定义了RuleSet中的规则(Rule)。

下面是HostRuleSet类的addRuleInstances方法的实现片段:

      
        public
      
      
        void
      
      
         addRuleInstances(Digester digester) { 
   digester.addObjectCreate(prefix 
      
      + "Host", "org.apache.catalina.core.StandardHost", "className"
      
        ); 
   digester.addSetProperties(prefix 
      
      + "Host"
      
        ); 
   digester.addRule(prefix 
      
      + "Host", 
      
        new
      
      
         CopyParentClassLoaderRule(digester)); 
   digester.addRule(prefix 
      
      + "Host"
      
        , 

      
      
        new
      
       LifecycleListenerRule (digester, "org.apache.catalina.startup.HostConfig", "hostConfigClass"));
    

正如代码中所示,当出现模式Server/Service/Engine/Host时,会创建一个org.apache.catalina.startup.HostConfig实例,并被添加到host,作为一个生命周期监听器。换句话说,HostConfig对象会处理StandardHost对象的start和stop方法触发的事件。

下面的代码是HostConfig的lifecycleEvent方法实现:

      
        public
      
      
        void
      
      
         lifecycleEvent(LifecycleEvent event) { 
   
      
      
        //
      
      
         Identify the host we are associated with 
      
      
        try
      
      
         { 
     host 
      
      =
      
         (Host) event.getLifecycle(); 
     
      
      
        if
      
       (host 
      
        instanceof
      
      
         StandardHost) { 
       
      
      
        int
      
       hostDebug =
      
         ((StandardHost) host).getDebug(); 
       
      
      
        if
      
       (hostDebug > 
      
        this
      
      
        .debug) { 
         
      
      
        this
      
      .debug =
      
         hostDebug; 
       } 
       setDeployXML(((StandardHost) host).isDeployXML()); 
       setLiveDeploy(((StandardHost) host).getLiveDeploy()); 
       setUnpackWARs(((StandardHost) host).isUnpackWARs()); 
     } 
   } 
      
      
        catch
      
      
         (ClassCastException e) { 
     log(sm.getString(
      
      "hostConfig.cce"
      
        , event.getLifecycle()), e); 
     
      
      
        return
      
      
        ; 
   } 
 
   
      
      
        //
      
      
         Process the event that has occurred 
      
      
        if
      
      
         (event.getType().equals(Lifecycle.START_EVENT)) 
     start (); 
   
      
      
        else
      
      
        if
      
      
         (event.getType().equals(Lifecycle.STOP_EVENT)) 
     stop(); 
}
      
    

如果变量host指向的对象是一个org.apache.catalina.core.StandardHost实例,会调用setDeployXML方法,setLiveDeploy方法和setUnpackWARs方法:

      
        setDeployXML(((StandardHost) host).isDeployXML()); 
setLiveDeploy(((StandardHost) host).getLiveDeploy());  
setUnpackWARs(((StandardHost) host).isUnpackWARs());
      
    

StandardHost类的isDeployXML方法指明host是否要部署一个描述文件,默认为true。liveDeploy属性指明host是否要周期性的检查是否有新的应用部署。unpackWARs属性指明host是否要解压缩war文件。
接收到START事件后,HostConfig的lifecycleEvent方法会调用start方法来部署web应用:

      
        protected
      
      
        void
      
      
         start() { 
   
      
      
        if
      
       (debug >= 1
      
        ) 
     log(sm.getString(
      
      "hostConfig.start"
      
        )); 
   
      
      
        if
      
      
         (host.getAutoDeploy()) { 
     deployApps(); 
   } 
   
      
      
        if
      
      
         (isLiveDeploy ()) { 
     threadStart(); 
   } 
}
      
    

当autoDeploy属性值为true时(默认为true),则start方法会调用deployApps方法。此外,若liveDeploy属性为true(默认为true),则该方法会开一个新线程调用threadStart方法。
deployApps方法从host中获取appBase属性值(默认为webapps),该值定义于server.xml文件中。部署进程会将%CATALINE_HOME%/webapps目录下的所有目录看做为Web应用程序的目录来执行部署工作。此外,该目录下找到的war文件和描述文件也会被部署。

deployApps方法实现如下:

      
        protected
      
      
        void
      
      
         deployApps() { 
   
      
      
        if
      
       (!(host 
      
        instanceof
      
      
         Deployer))      

      
      
        return
      
      
        ; 
   
      
      
        if
      
       (debug >= 1
      
        ) 
     log(sm.getString(
      
      "hostConfig.deploying"
      
        )); 
   File appBase 
      
      =
      
         appBase(); 
   
      
      
        if
      
       (!appBase.exists() || !
      
        appBase.isDirectory()) 
     
      
      
        return
      
      
        ; 
   String files[] 
      
      =
      
         appBase.list(); 
   deployDescriptors(appBase, files); 
   deployWARs(appBase, files); 
   deployDirectories(appBase, files); 
}
      
    

deployApps方法会调用其他三个方法,deployDescriptors,deployWARs和deployDirectories。对于所有方法,deployApps方法会传入appBase对象和appBase下所有的文件名的数组形式。context实例是通过其路径来标识的,所有的context必须有其唯一路径。已经被部署的contex实例t会被添加到HostConfig对象中已经部署的ArrayList中。因此,在部署一个context实例之前,deployDescriptors,deployWARs和deployDirectories方法必须确保已部署ArrayList中的没有相同路径的context实例。
注意,deployDescriptors,deployWARs和deployDirectories三个方法的调用顺序是固定的

下面方法为部署描述符:

      
        /**
      
      
        
     * Deploy XML context descriptors.
     
      
      
        */
      
      
        protected
      
      
        void
      
      
         deployDescriptors(File appBase, String[] files) {

        
      
      
        if
      
       (!
      
        deployXML)
           
      
      
        return
      
      
        ;

        
      
      
        for
      
       (
      
        int
      
       i = 0; i < files.length; i++
      
        ) {

            
      
      
        if
      
       (files[i].equalsIgnoreCase("META-INF"
      
        ))
                
      
      
        continue
      
      
        ;
            
      
      
        if
      
       (files[i].equalsIgnoreCase("WEB-INF"
      
        ))
                
      
      
        continue
      
      
        ;
            
      
      
        if
      
      
         (deployed.contains(files[i]))
                
      
      
        continue
      
      
        ;
            File dir 
      
      = 
      
        new
      
      
         File(appBase, files[i]);
            
      
      
        if
      
       (files[i].toLowerCase().endsWith(".xml"
      
        )) {

                deployed.add(files[i]);

                
      
      
        //
      
      
         Calculate the context path and make sure it is unique
      
      
                String file = files[i].substring(0, files[i].length() - 4
      
        );
                String contextPath 
      
      = "/" +
      
         file;
                
      
      
        if
      
       (file.equals("ROOT"
      
        )) {
                    contextPath 
      
      = ""
      
        ;
                }
                
      
      
        if
      
       (host.findChild(contextPath) != 
      
        null
      
      
        ) {
                    
      
      
        continue
      
      
        ;
                }

                
      
      
        //
      
      
         Assume this is a configuration descriptor and deploy it
      
      
                log(sm.getString("hostConfig.deployDescriptor"
      
        , files[i]));
                
      
      
        try
      
      
         {
                    URL config 
      
      =
                        
      
        new
      
       URL("file", 
      
        null
      
      
        , dir.getCanonicalPath());
                    ((Deployer) host).install(config, 
      
      
        null
      
      
        );
                } 
      
      
        catch
      
      
         (Throwable t) {
                    log(sm.getString(
      
      "hostConfig.deployDescriptor.error"
      
        ,
                                     files[i]), t);
                }

            }

        }

    }
      
    

部署WAR文件:

      
        /**
      
      
        
     * Deploy WAR files.
     
      
      
        */
      
      
        protected
      
      
        void
      
      
         deployWARs(File appBase, String[] files) {

        
      
      
        for
      
       (
      
        int
      
       i = 0; i < files.length; i++
      
        ) {

            
      
      
        if
      
       (files[i].equalsIgnoreCase("META-INF"
      
        ))
                
      
      
        continue
      
      
        ;
            
      
      
        if
      
       (files[i].equalsIgnoreCase("WEB-INF"
      
        ))
                
      
      
        continue
      
      
        ;
            
      
      
        if
      
      
         (deployed.contains(files[i]))
                
      
      
        continue
      
      
        ;
            File dir 
      
      = 
      
        new
      
      
         File(appBase, files[i]);
            
      
      
        if
      
       (files[i].toLowerCase().endsWith(".war"
      
        )) {

                deployed.add(files[i]);

                
      
      
        //
      
      
         Calculate the context path and make sure it is unique
      
      
                String contextPath = "/" +
      
         files[i];
                
      
      
        int
      
       period = contextPath.lastIndexOf("."
      
        );
                
      
      
        if
      
       (period >= 0
      
        )
                    contextPath 
      
      = contextPath.substring(0
      
        , period);
                
      
      
        if
      
       (contextPath.equals("/ROOT"
      
        ))
                    contextPath 
      
      = ""
      
        ;
                
      
      
        if
      
       (host.findChild(contextPath) != 
      
        null
      
      
        )
                    
      
      
        continue
      
      
        ;

                
      
      
        if
      
      
         (isUnpackWARs()) {

                    
      
      
        //
      
      
         Expand and deploy this application as a directory
      
      
                    log(sm.getString("hostConfig.expand"
      
        , files[i]));
                    
      
      
        try
      
      
         {
                        URL url 
      
      = 
      
        new
      
       URL("jar:file:" +
      
        
                                          dir.getCanonicalPath() 
      
      + "!/"
      
        );
                        String path 
      
      =
      
         expand(url);
                        url 
      
      = 
      
        new
      
       URL("file:" +
      
         path);
                        ((Deployer) host).install(contextPath, url);
                    } 
      
      
        catch
      
      
         (Throwable t) {
                        log(sm.getString(
      
      "hostConfig.expand.error"
      
        , files[i]),
                            t);
                    }

                } 
      
      
        else
      
      
         {

                    
      
      
        //
      
      
         Deploy the application in this WAR file
      
      
                    log(sm.getString("hostConfig.deployJar"
      
        , files[i]));
                    
      
      
        try
      
      
         {
                        URL url 
      
      = 
      
        new
      
       URL("file", 
      
        null
      
      
        ,
                                          dir.getCanonicalPath());
                        url 
      
      = 
      
        new
      
       URL("jar:" + url.toString() + "!/"
      
        );
                        ((Deployer) host).install(contextPath, url);
                    } 
      
      
        catch
      
      
         (Throwable t) {
                        log(sm.getString(
      
      "hostConfig.deployJar.error"
      
        ,
                                         files[i]), t);
                    }

                }

            }

        }

    }
      
    

也可以直接将Web应用程序整个目录复制到%CATALINA_HOME%/webapps目录下,部署目录:

      
        /**
      
      
        
     * Deploy directories.
     
      
      
        */
      
      
        protected
      
      
        void
      
      
         deployDirectories(File appBase, String[] files) {

        
      
      
        for
      
       (
      
        int
      
       i = 0; i < files.length; i++
      
        ) {

            
      
      
        if
      
       (files[i].equalsIgnoreCase("META-INF"
      
        ))
                
      
      
        continue
      
      
        ;
            
      
      
        if
      
       (files[i].equalsIgnoreCase("WEB-INF"
      
        ))
                
      
      
        continue
      
      
        ;
            
      
      
        if
      
      
         (deployed.contains(files[i]))
                
      
      
        continue
      
      
        ;
            File dir 
      
      = 
      
        new
      
      
         File(appBase, files[i]);
            
      
      
        if
      
      
         (dir.isDirectory()) {

                deployed.add(files[i]);

                
      
      
        //
      
      
         Make sure there is an application configuration directory
                
      
      
        //
      
      
         This is needed if the Context appBase is the same as the
                
      
      
        //
      
      
         web server document root to make sure only web applications
                
      
      
        //
      
      
         are deployed and not directories for web space.
      
      
                File webInf = 
      
        new
      
       File(dir, "/WEB-INF"
      
        );
                
      
      
        if
      
       (!webInf.exists() || !webInf.isDirectory() ||
                    !
      
        webInf.canRead())
                    
      
      
        continue
      
      
        ;

                
      
      
        //
      
      
         Calculate the context path and make sure it is unique
      
      
                String contextPath = "/" +
      
         files[i];
                
      
      
        if
      
       (files[i].equals("ROOT"
      
        ))
                    contextPath 
      
      = ""
      
        ;
                
      
      
        if
      
       (host.findChild(contextPath) != 
      
        null
      
      
        )
                    
      
      
        continue
      
      
        ;

                
      
      
        //
      
      
         Deploy the application in this directory
      
      
                log(sm.getString("hostConfig.deployDir"
      
        , files[i]));
                
      
      
        try
      
      
         {
                    URL url 
      
      = 
      
        new
      
       URL("file", 
      
        null
      
      
        , dir.getCanonicalPath());
                    ((Deployer) host).install(contextPath, url);
                } 
      
      
        catch
      
      
         (Throwable t) {
                    log(sm.getString(
      
      "hostConfig.deployDir.error"
      
        , files[i]),
                        t);
                }

            }

        }

    }
      
    

正如前面描述的, 如果变量liveDeploy的值为true,start方法会调用threadStart()方法

      
        if
      
      
         (isLiveDeploy()) {
            threadStart();
        }
      
    

threadStart()方法会派生一个新线程并调用run()方法,run()方法会定期检查是否有新应用要部署,或已部署的Web应用程序的web.xml是否有修改

下面的run()方法的实现(HostConfig类实现了java.lang.Runnable接口)

      
        /**
      
      
        
     * The background thread that checks for web application autoDeploy
     * and changes to the web.xml config.
     
      
      
        */
      
      
        public
      
      
        void
      
      
         run() {

        
      
      
        if
      
       (debug >= 1
      
        )
            log(
      
      "BACKGROUND THREAD Starting"
      
        );

        
      
      
        //
      
      
         Loop until the termination semaphore is set
      
      
        while
      
       (!
      
        threadDone) {

            
      
      
        //
      
      
         Wait for our check interval
      
      
                    threadSleep();

            
      
      
        //
      
      
         Deploy apps if the Host allows auto deploying
      
      
                    deployApps();

            
      
      
        //
      
      
         Check for web.xml modification
      
      
                    checkWebXmlLastModified();

        }

        
      
      
        if
      
       (debug >= 1
      
        )
            log(
      
      "BACKGROUND THREAD Stopping"
      
        );

    }
      
    

部署器用org.apache.catalina.Deployer接口表示,StandardHost实现了 Deployer接口,因此,StandardHost也是一个部署器,它是一个容器,Web应用可以部署到其中,或从中取消部署

下面是Deployer接口的定义:

      
        /*
      
      
         public interface Deployer extends Container { 
      
      
        */
      
      
        public
      
      
        interface
      
      
         Deployer  {
  
      
      
        public
      
      
        static
      
      
        final
      
       String PRE_INSTALL_EVENT = "pre-install"
      
        ;
   
      
      
        public
      
      
        static
      
      
        final
      
       String INSTALL_EVENT = "install"
      
        ;
    
      
      
        public
      
      
        static
      
      
        final
      
       String REMOVE_EVENT = "remove"
      
        ;
    
      
      
        public
      
      
         String getName();
   
      
      
        public
      
      
        void
      
       install(String contextPath, URL war) 
      
        throws
      
      
         IOException;
    
      
      
        public
      
      
        void
      
       install(URL config, URL war) 
      
        throws
      
      
         IOException;
  
      
      
        public
      
      
         Context findDeployedApp(String contextPath);
  
      
      
        public
      
      
         String[] findDeployedApps();
    
      
      
        public
      
      
        void
      
       remove(String contextPath) 
      
        throws
      
      
         IOException;
   
      
      
        public
      
      
        void
      
       start(String contextPath) 
      
        throws
      
      
         IOException;
    
      
      
        public
      
      
        void
      
       stop(String contextPath) 
      
        throws
      
      
         IOException;

}
      
    

StandardHost类使用一个辅助类( org.apache.catalina.core.StandardHostDeployer,与StandardHost类都实现了Deployer接口 ) 来完成部署与安装Web应用程序的相关任务,下面的代码片段演示了StandardHost对象如何将部署任务委托给StandardHostDeployer实例来完成

      
        /**
      
      
        
* The <code>Deployer</code> to whom we delegate application
* deployment requests.

      
      
        */
      
      
        private
      
       Deployer deployer = 
      
        new
      
       StandardHostDeployer(
      
        this
      
      
        );

      
      
        public
      
      
        void
      
       install(String contextPath, URL war) 
      
        throws
      
      
         IOException {
    deployer.install(contextPath, war);
}

      
      
        public
      
      
        synchronized
      
      
        void
      
       install(URL config, URL war) 
      
        throws
      
      
        
IOException {
    deployer.install(config, war);
}

      
      
        public
      
      
         Context findDeployedApp(String contextPath) {
    
      
      
        return
      
      
         (deployer.findDeployedApp(contextPath));
}

      
      
        public
      
      
         String[] findDeployedApps() {
    
      
      
        return
      
      
         (deployer.findDeployedApps());
}
        
public void remove(String contextPath) throws IOException { deployer.remove(contextPath); } public void start(String contextPath) throws IOException { deployer.start(contextPath); } public void stop(String contextPath) throws IOException { deployer.stop(contextPath); }

org.apache.catalina.core.StandardHostDeployer类是一个辅助类,帮助完成将Web应用程序部署到StandardHost实例的工作。StandardHostDeployer实例由StandardHost对象调用,在其构造函数中,会传入StandardHost类的实例

      
        public
      
      
         StandardHostDeployer(StandardHost host) {

        
      
      
        super
      
      
        ();
        
      
      
        this
      
      .host =
      
         host;

    }
      
    

下面的install()方法用于安装描述符,当HostConfig对象的deployDescriptors方法调用StandardHost实例的install()方法后, StandardHost实例调用该方法

      
        public
      
      
        synchronized
      
      
        void
      
       install(URL config, URL war) 
      
        throws
      
      
         IOException {

        
      
      
        //
      
      
         Validate the format and state of our arguments
      
      
        if
      
       (config == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.configRequired"
      
        ));

        
      
      
        if
      
       (!
      
        host.isDeployXML())
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.configNotAllowed"
      
        ));

        
      
      
        //
      
      
         Calculate the document base for the new web application (if needed)
      
      
        String docBase = 
      
        null
      
      ; 
      
        //
      
      
         Optional override for value in config file
      
      
        if
      
       (war != 
      
        null
      
      
        ) {
            String url 
      
      =
      
         war.toString();
            host.log(sm.getString(
      
      "standardHost.installingWAR"
      
        , url));
            
      
      
        //
      
      
         Calculate the WAR file absolute pathname
      
      
        if
      
       (url.startsWith("jar:"
      
        )) {
                url 
      
      = url.substring(4, url.length() - 2
      
        );
            }
            
      
      
        if
      
       (url.startsWith("file://"
      
        ))
                docBase 
      
      = url.substring(7
      
        );
            
      
      
        else
      
      
        if
      
       (url.startsWith("file:"
      
        ))
                docBase 
      
      = url.substring(5
      
        );
            
      
      
        else
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                    (sm.getString(
      
      "standardHost.warURL"
      
        , url));

        }

        
      
      
        //
      
      
         Install the new web application
      
      
        this
      
      .context = 
      
        null
      
      
        ;
        
      
      
        this
      
      .overrideDocBase =
      
         docBase;
        InputStream stream 
      
      = 
      
        null
      
      
        ;
        
      
      
        try
      
      
         {
            stream 
      
      =
      
         config.openStream();
            Digester digester 
      
      =
      
         createDigester();
            digester.setDebug(host.getDebug());
            digester.clear();
            digester.push(
      
      
        this
      
      
        );
            digester.parse(stream);
            stream.close();
            stream 
      
      = 
      
        null
      
      
        ;
        } 
      
      
        catch
      
      
         (Exception e) {
            host.log
                (sm.getString(
      
      "standardHost.installError"
      
        , docBase), e);
            
      
      
        throw
      
      
        new
      
      
         IOException(e.toString());
        } 
      
      
        finally
      
      
         {
            
      
      
        if
      
       (stream != 
      
        null
      
      
        ) {
                
      
      
        try
      
      
         {
                    stream.close();
                } 
      
      
        catch
      
      
         (Throwable t) {
                    ;
                }
            }
        }

    }
      
    

第二个install()方法用于安装WAR文件或目录

      
        public
      
      
        synchronized
      
      
        void
      
      
         install(String contextPath, URL war)
        
      
      
        throws
      
      
         IOException {

        
      
      
        //
      
      
         Validate the format and state of our arguments
      
      
        if
      
       (contextPath == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathRequired"
      
        ));
        
      
      
        if
      
       (!contextPath.equals("") && !contextPath.startsWith("/"
      
        ))
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathFormat"
      
        , contextPath));
        
      
      
        if
      
       (findDeployedApp(contextPath) != 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (sm.getString(
      
      "standardHost.pathUsed"
      
        , contextPath));
        
      
      
        if
      
       (war == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.warRequired"
      
        ));

        
      
      
        //
      
      
         Calculate the document base for the new web application
      
      
        host.log(sm.getString("standardHost.installing"
      
        ,
                              contextPath, war.toString()));
        String url 
      
      =
      
         war.toString();
        String docBase 
      
      = 
      
        null
      
      
        ;
        
      
      
        if
      
       (url.startsWith("jar:"
      
        )) {
            url 
      
      = url.substring(4, url.length() - 2
      
        );
        }
        
      
      
        if
      
       (url.startsWith("file://"
      
        ))
            docBase 
      
      = url.substring(7
      
        );
        
      
      
        else
      
      
        if
      
       (url.startsWith("file:"
      
        ))
            docBase 
      
      = url.substring(5
      
        );
        
      
      
        else
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.warURL"
      
        , url));

        
      
      
        //
      
      
         Install the new web application
      
      
        try
      
      
         {
            Class clazz 
      
      =
      
         Class.forName(host.getContextClass());
            Context context 
      
      =
      
         (Context) clazz.newInstance();
            context.setPath(contextPath);
            
            context.setDocBase(docBase);
            
      
      
        if
      
       (context 
      
        instanceof
      
      
         Lifecycle) {
                clazz 
      
      =
      
         Class.forName(host.getConfigClass());
                LifecycleListener listener 
      
      =
      
        
                    (LifecycleListener) clazz.newInstance();
                ((Lifecycle) context).addLifecycleListener(listener);
            }
            host.fireContainerEvent(PRE_INSTALL_EVENT, context);
            host.addChild(context);
            host.fireContainerEvent(INSTALL_EVENT, context);
        } 
      
      
        catch
      
      
         (Exception e) {
            host.log(sm.getString(
      
      "standardHost.installError"
      
        , contextPath),
                     e);
            
      
      
        throw
      
      
        new
      
      
         IOException(e.toString());
        }

    }
      
    

start()方法用于启动Context实例:

      
        public
      
      
        void
      
       start(String contextPath) 
      
        throws
      
      
         IOException {
        
      
      
        //
      
      
         Validate the format and state of our arguments
      
      
        if
      
       (contextPath == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathRequired"
      
        ));
        
      
      
        if
      
       (!contextPath.equals("") && !contextPath.startsWith("/"
      
        ))
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathFormat"
      
        , contextPath));
        Context context 
      
      =
      
         findDeployedApp(contextPath);
        
      
      
        if
      
       (context == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathMissing"
      
        , contextPath));
        host.log(
      
      "standardHost.start " +
      
         contextPath);
        
      
      
        try
      
      
         {
            ((Lifecycle) context).start();
        } 
      
      
        catch
      
      
         (LifecycleException e) {
            host.log(
      
      "standardHost.start " + contextPath + ": "
      
        , e);
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (
      
      "standardHost.start " + contextPath + ": " +
      
         e);
        }
    }
      
    

stop()方法用于停止Context实例:

      
        public
      
      
        void
      
       stop(String contextPath) 
      
        throws
      
      
         IOException {

        
      
      
        //
      
      
         Validate the format and state of our arguments
      
      
        if
      
       (contextPath == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathRequired"
      
        ));
        
      
      
        if
      
       (!contextPath.equals("") && !contextPath.startsWith("/"
      
        ))
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathFormat"
      
        , contextPath));
        Context context 
      
      =
      
         findDeployedApp(contextPath);
        
      
      
        if
      
       (context == 
      
        null
      
      
        )
            
      
      
        throw
      
      
        new
      
      
         IllegalArgumentException
                (sm.getString(
      
      "standardHost.pathMissing"
      
        , contextPath));
        host.log(
      
      "standardHost.stop " +
      
         contextPath);
        
      
      
        try
      
      
         {
            ((Lifecycle) context).stop();
        } 
      
      
        catch
      
      
         (LifecycleException e) {
            host.log(
      
      "standardHost.stop " + contextPath + ": "
      
        , e);
            
      
      
        throw
      
      
        new
      
      
         IllegalStateException
                (
      
      "standardHost.stop " + contextPath + ": " +
      
         e);
        }

    }
      
    

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

本系列How Tomcat Works系本人原创 

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

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

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

How Tomcat Works(二十)


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

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

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

【本文对您有帮助就好】

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

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