Stories

Detail Return Return

【Tomcat】《How Tomcat Works》英文版GPT翻譯(第十八章) - Stories Detail

Chapter 18: Deployer

Overview(概述)

For a web application to be available, the context representing it must first be deployed to a host. In Tomcat, a context can be deployed as a WAR file or by copying the whole application to the webapps directory under the Tomcat installation directory. For each application you deploy, you can optionally have a descriptor file that contains the configuration settings for the context. A descriptor file takes the form of an XML document.

要使一個Web應用程序可用,首先必須將代表它的上下文部署到主機上。

在Tomcat中,上下文可以以WAR文件的形式部署,也可以通過將整個應用程序複製到Tomcat安裝目錄下的webapps目錄中進行部署。

對於每個部署的應用程序,可以選擇性地擁有一個包含上下文配置設置的描述符文件。

描述符文件採用XML文檔的形式。

Note Tomcat 4 and 5 come with two applications for managing Tomcat and applications deployed to it, the manager application and the admin application. The class files for both applications are in the %CATALINA_HOME%/server/webapps directory. Both applications come with descriptor files, which are manager.xml and admin.xml, respectively. In Tomcat 4, these descriptors reside in the %CATALINA_HOME%/webapps directory; in Tomcat 5 they live in the corresponding application directories, i.e. in the %CATALINA_HOME%/server/webapps/admin and %CATALINA_HOME%/server/webapps/manager, respectively.

注意:Tomcat 4和5都附帶了兩個用於管理Tomcat和部署到Tomcat上的應用程序的應用程序,即管理器應用程序和管理員應用程序。

這兩個應用程序的類文件位於%CATALINA_HOME%/server/webapps目錄中。

這兩個應用程序都附帶了描述符文件,分別是manager.xml和admin.xml。

在Tomcat 4中,這些描述符位於%CATALINA_HOME%/webapps目錄中;

在Tomcat 5中,它們位於相應的應用程序目錄中,

即%CATALINA_HOME%/server/webapps/admin

和%CATALINA_HOME%/server/webapps/manager。

This chapter discusses web application deployment using a deployer, which is represented by the org.apache.catalina.Deployer interface. A deployer is associated with a host and is used to install child contexts. Installing a context to a host means creating an instance of the StandardContext class and adding that instance to the host. A child context is started when the parent host is started (because a container's start method always calls the start method of its child containers, except for a wrapper). However, a deployer can also be used to start and stop each context individually.

本章討論了使用部署器進行Web應用程序部署的方法,部署器由org.apache.catalina.Deployer接口表示。

部署器與主機關聯,並用於安裝子上下文。

將上下文安裝到主機意味着創建StandardContext類的實例,並將該實例添加到主機中。

當父主機啓動時,將啓動子上下文(因為容器的start方法總是調用其子容器的start方法,除了包裝器)。

然而,部署器也可以用於單獨啓動和停止每個上下文。

In this chapter you will first learn how a Tomcat deployment deploys web applications in a host. This chapter will then explain about the Deployer interface and its standard implementation, the org.apache.catalina.core.StandardHostDeployer class.

在本章中,您將首先了解Tomcat部署如何在主機中部署Web應用程序。

然後,本章將解釋Deployer接口及其標準實現org.apache.catalina.core.StandardHostDeployer類。

Deploying A Web Context(部署網絡情境)

In Chapter 15, you used the following code to instantiate the StandardHost class and add a Context instance as the host's child container.

在第15章,您使用以下代碼來實例化StandardHost類,並將一個Context實例作為主機的子容器添加進去。

Context context = new StandardContext();
context.setPath("/app1");
context.setDocBase("app1");
LifecycleListener listener = new ContextConfig();
((Lifecycle) context).addLifecycleListener(listener);
Host host = new StandardHost();
host.addChild(context);

That was how we deployed our application. However, such code does not exist in Tomcat. Then, how does a context get added to a host in a real life deployment? The answer lies in a lifecycle listener of type org.apache.catalina.startup.HostConfig in the StandardHost instance.

這就是我們部署應用程序的方式。

然而,在Tomcat中並不存在這樣的代碼。

那麼,在實際部署中,一個上下文是如何添加到主機中的呢?

答案在於StandardHost實例中的類型為org.apache.catalina.startup.HostConfig的生命週期監聽器。

When the start method on the StandardHost instance is called, it triggers a START event. The HostConfig instance responds to it by calling its own start method, which in turn deploys and installs all web applications available in the specified directories. Here are the details.

當調用StandardHost實例的start方法時,會觸發一個START事件。

HostConfig實例會響應該事件,通過調用自己的start方法來部署和安裝指定目錄中的所有Web應用程序。以下是詳細信息。

Recall that Chapter 15, "Digester", explained how you could use a Digester object to parse an XML file. However it did not discuss all the rules in the Digester object. One subject of discussion that it skipped was deployer, which is the topic of this chapter.

回顧一下第15章中的“Digester”部分,它解釋瞭如何使用Digester對象來解析XML文件。

然而,它並未討論Digester對象中的所有規則。

它跳過的一個討論主題是部署者(deployer),這也是本章的主題。

The org.apache.catalina.startup.Catalina class is a startup class that employs a Digester to convert XML elements in the server.xml file to Java objects. The Catalina class defines the createStartDigester method for adding rules to the Digester. One line in the createStartDigester method is this:

org.apache.catalina.startup.Catalina類是一個啓動類,它使用Digester將server.xml文件中的XML元素轉換為Java對象。

Catalina類定義了createStartDigester方法,用於向Digester添加規則。

在createStartDigester方法中的一行代碼是這樣的:

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

The org.apache.catalina.startup.HostRuleSet class extends the org.apache.commons.digester.RuleSetBase class (also discussed in Chapter 15). As a subclass of RuleSetBase, the HostRuleSet class must provide the implementation of the addRuleInstances method, which defines the rule(s) for the RuleSet. Here is a fragment of the HostRuleSet class's addRuleInstances method.

org.apache.catalina.startup.HostRuleSet類擴展了org.apache.commons.digester.RuleSetBase類(也將在第15章中討論)。

作為 RuleSetBase 的子類,HostRuleSet 類必須提供 addRuleInstances 方法的實現,該方法定義了 RuleSet 的規則。

下面是 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"));

What the code says is, the occurrence of the Server/Service/Engine/Host pattern in the server.xml file creates an instance of org.apache.catalina.startup.HostConfig class and adds it to the host as a lifecycle listener. In other words, the HostConfig class handles the events fired by the StandardHost's start and stop methods.

代碼所述的是,server.xml文件中的Server/Service/Engine/Host模式的出現會創建org.apache.catalina.startup.HostConfig類的一個實例,並將其作為生命週期監聽器添加到主機中。

換句話説,HostConfig類處理StandardHost的start和stop方法觸發的事件。

Listing 18.1 offers the lifecycleEvent method of the HostConfig class. This method is an event handler. Because the HostConfig is a listener for a StandardHost instance, every time the StandardHost is started or stopped, the lifecycleEvent method will be invoked.

清單18.1提供了HostConfig類的lifecycleEvent方法。

這個方法是一個事件處理程序。

因為HostConfig是StandardHost實例的監聽器,所以每當StandardHost啓動或停止時,lifecycleEvent方法都會被調用。

Listing 18.1: The lifecycleEvent method of the HostConfig class.

清單18.1: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();
}

If the host is an instance of org.apache.catalina.core.StandardHost, the setDeployXML,setLiveDeploy, and setUnpackWARs methods are called.

如果主機是 org.apache.catalina.core.StandardHost 的實例,則會調用 setDeployXML、setLiveDeploy 和 setUnpackWARs 方法。

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

The isDeployXML method of the StandardHost class indicates whether or not the host should deploy a context's descriptor file. By default the value of the deployXML property is true. The liveDeploy property indicates whether or not the host should periodically check for a new deployment, and the unpackWARs property specifies whether or not to unpack applications deployed as WAR files.

StandardHost類的isDeployXML方法指示主機是否應該部署上下文的描述符文件。

默認情況下,deployXML屬性的值為true。

liveDeploy屬性指示主機是否應定期檢查新的部署,而unpackWARs屬性指定是否解壓作為WAR文件部署的應用程序。

Upon receiving a START event notification, the HostConfig object's lifecycleEvent method calls the start method to deploy applications. This method is given in Listing 18.2.

Upon receiving a START event notification, the HostConfig object's lifecycleEvent method calls the start method to deploy applications. This method is given in Listing 18.2.

在接收到START事件通知後,HostConfig對象的lifecycleEvent方法調用start方法來部署應用程序。

該方法在代碼清單18.2中給出。

Listing 18.2: The start method of the HostConfig class

代碼清單18.2:HostConfig類的start方法

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

The start method calls the deployApps method if the autoDeploy property is true (by default, its value is true). Also, it spawns a new thread by calling the threadStart method if liveDeploy is true (which it is, by default). Live deploy is discussed further in the subsection "Live Deploy" later in this section.

start方法在autoDeploy屬性為true(默認為true)時調用deployApps方法。

此外,如果liveDeploy屬性為true(默認為true),它還通過調用threadStart方法生成一個新線程。

關於live deploy的詳細信息將在本節的子部分"Live Deploy"中進一步討論。

The deployApps method obtains the appBase property of the host. appBase by default has the value of webapps (See Tomcat's server.xml file). The deployment process regards all directories under the %CATALINE_HOME%/webapps directory as application directories to be deployed. In addition, all WAR and descriptor files found in this directory are to be deployed as well.

deployApps方法獲取主機的appBase屬性。默認情況下,appBase的值為webapps(請參閲Tomcat的server.xml文件)。

部署過程將所有位於%CATALINE_HOME%/webapps目錄下的目錄視為要部署的應用程序目錄。

此外,該目錄中找到的所有WAR和描述符文件也將被部署。

The deployApps method is given in Listing 18.3.

Listing 18.3中給出了deployApps方法的代碼。

Listing 18.3: The deployApps method

清單 18.3: 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);  
}

The deployApps method calls three other methods, deployDescriptors, deployWARs, and deployDirectories. To all methods, deployApps passes the appBase File and the array of files in the webapps directory. A context is identified by its path, and all deployed contexts must have unique paths. A context that has been deployed is added to the deployed ArrayList in the HostConfig object. Therefore, before deploying a context, the deployDescriptors, deployWARs, and deployDirectories methods make sure that the deployed ArrayList does not contain a context having an identical path.

deployApps方法調用了三個其他方法:deployDescriptors、deployWARs和deployDirectories。

對於所有方法,deployApps傳遞了appBase文件和webapps目錄中的文件數組。

一個上下文通過其路徑進行標識,所有部署的上下文必須具有唯一的路徑。

已部署的上下文將添加到HostConfig對象的deployed ArrayList中。

因此,在部署上下文之前,deployDescriptors、deployWARs和deployDirectories方法確保deployed ArrayList不包含具有相同路徑的上下文。

We now look at each of the three deployment methods in turn. After reading the three subsections below, you should be able to answer this question: Is the order the three methods are called important? (The answer is yes)

現在我們依次查看這三個部署方法。

閲讀下面的三個小節後,您應該能夠回答這個問題:這三個方法的調用順序重要嗎?(答案是肯定的)

Deploying a Descriptor(部署描述符)

You can write an XML file that describes the context object. For instance, the admin and manager applications that accompany Tomcat 4 and 5 have the descriptors given in Listings 18.4 and 18.5, respectively.

您可以編寫一個 XML 文件來描述上下文對象。

例如,Tomcat 4 和 5 中的管理員和管理程序的描述符分別如清單 18.4 和 18.5 所示。

Listing 18.4: The descriptor for the admin application (admin.xml)

清單 18.4:管理應用程序的描述符 (admin.xml)

<Context path="/admin" docBase="../server/webapps/admin"
 debug="0" privileged="true">
 <!-- Uncomment this Valve to limit access to the Admin app to
 localhost for obvious security reasons. Allow may be a comma-
 separated list of hosts (or even regular expressions).
 <Valve className="org.apache.catalina.valves.RemoteAddrValve"
 allow="127.0.0.1"/>
 -->
 <Logger className="org.apache.catalina.logger.FileLogger"
 prefix="localhost_admin_log." suffix=".txt"
 timestamp="true"/>
</Context>

Listing 18.5: The descriptor for the manager application (manager.xml)

清單 18.5:管理程序的描述符(manager.xml)`

<Context path="/manager" docBase="../server/webapps/manager"
 debug="0" privileged="true">
 <!-- Link to the user database we will get roles from -->
 <ResourceLink name="users" global="UserDatabase"
 type="org.apache.catalina.UserDatabase"/>
</Context>

Note that both descriptors have a Context element and the docBase attributes refer to %CATALINA_HOME%/server/webapps/admin and %CATALINA_HOME%/server/webapps/manager, respectively, which indicate that the admin and manager applications are not deployed to the usual place.

請注意,這兩個描述符都有一個Context元素,而docBase屬性分別引用了%CATALINA_HOME%/server/webapps/admin和%CATALINA_HOME%/server/webapps/manager,這表明admin和manager應用程序沒有部署到通常的位置。

The HostConfig class uses the deployDescriptors method in Listing 18.6 to deploy all XML files found in %CATALINA_HOME%/webapps in Tomcat 4 and in the subdirectories of %CATALINA_HOME%/server/webapps/ in Tomcat 5.

HostConfig類在Tomcat 4中使用deployDescriptors方法(見清單18.6)來部署在%CATALINA_HOME%/webapps中找到的所有XML文件,在Tomcat 5中使用%CATALINA_HOME%/server/webapps/的子目錄。

Listing 18.6: The deployDescriptors method in HostConfig

清單18.6:HostConfig中的deployDescriptors方法


    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);
                }
            }
        }
    }

Deploying a WAR File(部署 WAR 文件)

You can deploy a web application as a WAR file. The HostConfig class employs the deployWARs method in Listing 18.7 to deploy any WAR files in the %CATALINA_HOME%/webapps directory.

您可以將Web應用程序部署為WAR文件。

HostConfig類使用List 18.7中的deployWARs方法來部署%CATALINA_HOME%/webapps目錄中的任何WAR文件。

Listing 18.7: The deployWARs method in HostConfig

List 18.7:HostConfig中的deployWARs方法。


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);
                }
            }
        }
    }
}

Deploying a Directory(部署目錄)

Alternatively, you can deploy an application as it is by copying the whole directory to the %CATALINA_HOME%/webapps directory. HostConfig uses the deployDirectories in Listing 18.8 to deploy these applications.

另一種方法是將整個目錄複製到%CATALINA_HOME%/webapps目錄中,將應用程序部署為它本身。

HostConfig使用清單18.8中的deployDirectories方法來部署這些應用程序。

Listing 18.8: The deployDirectories method in HostConfig

清單18.8:HostConfig中的deployDirectories方法


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);
            }
        }
    }
}

Live Deploy(實時部署)

As mentioned previously, a StandardHost instance uses a HostConfig object as a lifecycle listener. When the StandardHost object is started, its start method fires a START event. In response to this START event, the lifecycleEvent method in HostConfig, the event handler in HostConfig, calls the start method. In Tomcat 4 the last line of this start method calls the threadStart method if the liveDeploy property is true (by default, this property is true).

如前所述,StandardHost實例使用HostConfig對象作為生命週期監聽器。

當StandardHost對象啓動時,它的start方法觸發一個START事件。

作為對此START事件的響應,HostConfig中的lifecycleEvent方法,即HostConfig中的事件處理程序,調用start方法。

在Tomcat 4中,如果liveDeploy屬性為true(默認情況下為true),則start方法的最後一行調用threadStart方法。

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

The threadStart method spawns a new thread that invokes the run method. The run method regularly checks for a new deployment and if any of the web.xml files of the existing deployed applications has been modified. The run method is presented in Listing 18.9.

threadStart 方法會生成一個調用運行方法的新線程。

運行方法會定期檢查是否有新的部署,以及現有部署應用程序的 web.xml 文件是否被修改。

運行方法如清單 18.9 所示。

Listing 18.9: The run method in HostConfig in Tomcat 4

清單 18.9:Tomcat 4 中 HostConfig 的運行方法

  
/**  
 * 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");  
}

The threadSleep method sends the thread to sleep for the duration indicated by the checkInterval property. By default, the value of this property is 15, meaning that checking is conducted every 15 seconds.

threadSleep方法會使線程休眠一段時間,時間長度由checkInterval屬性指定。默認情況下,該屬性的值為15,意味着每隔15秒進行一次檢查。

In Tomcat 5, the HostConfig class does not utilize a special thread. Instead, the backgroundProcess method of the StandardHost class fires a "check" event periodically:

在Tomcat 5中,HostConfig類不使用特殊的線程。

相反,StandardHost類的backgroundProcess方法會定期觸發一個“檢查”事件。

public void backgroundProcess() {
 lifecycle.fireLifecycleEvent("check", null);
}

Note The backgroundProcess method is periodically invoked by a special thread that serves all background processings in the containers.

注意 backgroundProcess 方法由一個特殊線程定期調用,該線程負責容器中的所有後台處理。

Upon receiving a "check" event, the lifecycle listener (the HostConfig object) calls its check method that performs the checking.

收到 "檢查 "事件後,生命週期監聽器(HostConfig 對象)會調用其檢查方法執行檢查。

public void lifecycleEvent(LifecycleEvent event) {
     if (event.getType().equals("check"))
     check();
     ...

The check method in the HostConfig class in Tomcat 5 is given in Listing 18.10.

Tomcat 5 中 HostConfig 類的檢查方法見清單 18.10。

Listing 18.10: The check method in HostConfig in Tomcat 5

清單 18.10:Tomcat 5 中 HostConfig 的檢查方法

protected void check() {
 if (host.getAutoDeploy()) {
 // Deploy apps if the Host allows auto deploying
 deployApps();
 // Check for web.xml modification
 checkContextLastModified();
 }
}

As you can see, the check method calls the deployApps method. The deployApps method in both Tomcat 4 and Tomcat 5 deploys the web applications and was given in Listing 18.3. As previously discussed, this method calls the deployDescriptors, deployWARs, and deployDirectories methods.

如您所見,check方法調用了deployApps方法。

在Tomcat 4和Tomcat 5中,deployApps方法部署了Web應用程序,並在第18.3節中給出了具體實現。

正如之前討論的那樣,該方法調用了deployDescriptors、deployWARs和deployDirectories方法。

The check method in Tomcat 5 also calls the checkContextLastModified method that iterates all deployed contexts and checks the timestamps of the web.xml file and the contents of the WEB-INF directory in each context. If any of the checked resources has changed, the context is restarted. In addition, the checkContextLastModified method also checks the timestamps of all deployed WAR files and redeploys an application whose WAR file has been modified.

在Tomcat 5中,check方法還調用了checkContextLastModified方法,該方法迭代了所有已部署的上下文,並檢查每個上下文中的web.xml文件和WEB-INF目錄的時間戳。

如果任何被檢查的資源發生了變化,上下文將會被重啓。

此外,checkContextLastModified方法還檢查了所有已部署的WAR文件的時間戳,並重新部署那些WAR文件發生了修改的應用程序。

In Tomcat 4, the run method of the background thread calls the checkWebXmlLastModified method that performs a similar task to the checkContextLastModified method in Tomcat 5.

在Tomcat 4中,後台線程的run方法調用了checkWebXmlLastModified方法,該方法執行了與Tomcat 5中的checkContextLastModified方法類似的任務。

The Deployer Interface(部署界面)

A deployer is represented by the org.apache.catalina.Deployer interface. The StandardHost class implements the Deployer interface. Therefore, a StandardHost instance is also a deployer and it is a container into which web applications can be deployed and undeployed. The Deployer interface is presented in Listing 18.11.

部署者由org.apache.catalina.Deployer接口表示。

StandardHost類實現了Deployer接口。

因此,StandardHost實例也是一個部署者,它是一個可以部署和卸載Web應用程序的容器。

Deployer接口的定義如下(見第18.11節):

Listing 18.11: The Deployer interface

第18.11節:部署者接口


package org.apache.catalina;
        import java.io.IOException;
        import java.net.URL;
/**
 * A <b>Deployer</b> is a specialized Container into which web
 * applications can be deployed and undeployed. Such a Container
 * will create and install child Context instances for each deployed
 * application. The unique key for each web application will be the
 * context path to which it is attached.
 *
 * @author Craig R. McClanahan
 * @version $Revision: 1.6 $ $Date: 2002/04/09 23:48:21 $
 */
public interface Deployer {
    /**
     * The ContainerEvent event type sent when a new application is
     * being installed by <code>install()</code>, before it has been
     * started.
     */
    public static final String PRE_INSTALL_EVENT = "pre-install";
    /**
     * The ContainerEvent event type sent when a new application is
     * installed by <code>install()</code>, after it has been started.
     */
    public static final String INSTALL_EVENT = "install";
    /**
     * The ContainerEvent event type sent when an existing application is
     * removed by <code>remove()</code>.
     */
    public static final String REMOVE_EVENT = "remove";
    /**
     * Return the name of the Container with which this Deployer is
     * associated.
     */
    public String getName();
    /**
     * Install a new web application, whose web application archive is at
     * the specified URL, into this container with the specified context.
     * path. A context path of "" (the empty string) should be used for
     * the root application for this container. Otherwise, the context
     * path must start with a slash.
     * <p>
     * If this application is successfully installed, a ContainerEvent of
     * type <code>INSTALL_EVENT</code> will be sent to all registered
     * listeners,
     * with the newly created <code>Context</code> as an argument.
     *
     * @param contextPath The context path to which this application
     * should be installed (must be unique)
     * @param war A URL of type "jar:" that points to a WAR file, or type
     * "file:" that points to an unpacked directory structure containing
     * the web application to be installed
     *
     * @exception IllegalArgumentException if the specified context path
     * is malformed (it must be "" or start with a slash)
     * @exception IllegalStateException if the specified context path
     * is already attached to an existing web application
     * @exception IOException if an input/output error was encountered
     * during installation
     */
    public void install(String contextPath, URL war) throws IOException;
    /**
     * <p>Install a new web application, whose context configuration file
     * (consisting of a <code>&lt;Context&gt;</code> element) and web
     * application archive are at the specified URLs.</p>
     *
     * <p>If this application is successfully installed, a ContainerEvent
     * of type <code>INSTALL_EVENT</code> will be sent to all registered
     * listeners, with the newly created <code>Context</code> as an
     * argument.
     * </p>
     *
     * @param config A URL that points to the context configuration file
     * to be used for configuring the new Context
     * @param war A URL of type "jar:" that points to a WAR file, or type
     * "file:" that points to an unpacked directory structure containing
     * the web application to be installed
     *
     * @exception IllegalArgumentException if one of the specified URLs
     * is null
     * @exception IllegalStateException if the context path specified in
     * the context configuration file is already attached to an existing
     * web application
     * @exception IOException if an input/output error was encountered
     * during installation
     */
    public void install(URL config, URL war) throws IOException;
    /**
     * Return the Context for the deployed application that is associated
     * with the specified context path (if any); otherwise return
     * <code>null</code>.
     *
     * @param contextPath The context path of the requested web
     * application
     */
    public Context findDeployedApp(String contextPath);
    /**
     * Return the context paths of all deployed web applications in this
     * Container. If there are no deployed applications, a zero-length
     * array is returned.
     */
    public String[] findDeployedApps();
    /**
     * Remove an existing web application, attached to the specified
     * context path. If this application is successfully removed, a
     * ContainerEvent of type <code>REMOVE_EVENT</code> will be sent to
     * all registered listeners, with the removed <code>Context</code> as
     * an argument.
     *
     * @param contextPath The context path of the application to be
     * removed
     *
     * @exception IllegalArgumentException if the specified context path
     * is malformed (it must be "" or start with a slash)
     * @exception IllegalArgumentException if the specified context path
     * does not identify a currently installed web application
     * @exception IOException if an input/output error occurs during
     * removal
     */
    public void remove(String contextPath) throws IOException;
    /**
     * Start an existing web application, attached to the specified
     * context path. Only starts a web application if it is not running.
     *
     * @param contextPath The context path of the application to be
     * started
     * @exception IllegalArgumentException if the specified context path
     * is malformed (it must be "" or start with a slash)
     * @exception IllegalArgumentException if the specified context path
     * does not identify a currently installed web application
     * @exception IOException if an input/output error occurs during
     * startup
     */
    public void start(String contextPath) throws IOException;
    /**
     * Stop an existing web application, attached to the specified
     * context path. Only stops a web application if it is running.
     *
     * @param contextPath The context path of the application to be
     * stopped
     * @exception IllegalArgumentException if the specified context path
     * is malformed (it must be "" or start with a slash)
     * @exception IllegalArgumentException if the specified context path
     * does not identify a currently installed web application
     * @exception IOException if an input/output error occurs while
     * stopping the web application
     */
    public void stop(String contextPath) throws IOException;
}

The StandardHost class employs a helper class (org.apache.catalina.core.StandardHostDeployer) for performing tasks related to deploying and installing a Web application. You can see in the following fragment of StandardHost how it delegates the task of deploying and installing web applications to an instance of StandardHostDeployer:

StandardHost 類使用一個輔助類(org.apache.catalina.core.StandardHostDeployer)來執行與部署和安裝 Web 應用程序相關的任務。

在 StandardHost 的以下片段中,您可以看到它是如何將部署和安裝 Web 應用程序的任務委託給 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);
    }

StandardHostDeployer is discussed in the next section.

The StandardHostDeployer Class(標準主機部署程序類)

The org.apache.catalina.core.StandardHostDeployer class is a helper class that helps deploy and install web applications in a StandardHost. StandardHostDeployer was designed to be used by a StandardHost object, as indicated by its constructor that accepts a StandardHost instance.

org.apache.catalina.core.StandardHostDeployer 類是一個輔助類,可幫助在 StandardHost 中部署和安裝網絡應用程序。

StandardHostDeployer 設計用於 StandardHost 對象,其構造函數接受一個 StandardHost 實例。

public StandardHostDeployer(StandardHost host) {
 super();
 this.host = host;
}

The methods in this class are explained in the following sub-sections.

這個類中的方法在下面的小節中進行了解釋。

Installing a Descriptor(安裝描述符)

The StandardHostDeployer class has two install methods. The first one, which is the topic of this subsection, is used to install a descriptor. The second one, discussed in the next subsection, is used to install a WAR file or a directory.

StandardHostDeployer類有兩個安裝方法。

第一個方法,即本小節的主題,用於安裝描述符。

第二個方法,在下一個小節中討論,用於安裝WAR文件或目錄。

The install method for installing descriptors is given in Listing 18.12. A StandardHost instance calls this method after its install method is called by the deployDescriptors method in a HostConfig object.

安裝描述符的方法如清單18.12所示。

在HostConfig對象的deployDescriptors方法調用StandardHost實例的安裝方法之後,會調用這個方法。

Listing 18.12: The install method for installing descriptors

清單18.12:安裝描述符的方法


    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) {
                    ;
                }
            }
        }
    }

Installing a WAR file and a Directory(部署 WAR 文件和目錄)

The second install method accepts a String representation of a context path and a URL representing a WAR file. This install method is given in Listing 18.13.

第二個安裝方法接受上下文路徑的字符串表示和表示 WAR 文件的 URL。

清單 18.13 給出了這種 install 方法。

Listing 18.13: The install method for installing a WAR file or a directory

清單 18.13:安裝 WAR 文件或目錄的 install 方法


    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());
        }
    }

Note that once a context is installed, it is added to the StandardHost.

請注意,一旦部署了上下文,它就會被添加到 StandardHost 中。

Starting A Context(啓動A環境)

The start method in StandardHostDeployer is used to start a context. It is given in Listing 18.14.

StandardHostDeployer 中的 start 方法用於啓動上下文。該方法在清單 18.14 中給出。

Listing 18.14: The start method of the StandardHostDeployer class

清單 18.14:StandardHostDeployer 類的 start 方法


    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);
        }
    }

Stopping A Context(停止A環境)

To stop a context, you call the stop method of StandardHostDeployer in Listing 18.15.

要停止上下文,請調用清單 18.15 中 StandardHostDeployer 的 stop 方法。

Listing 18.15: The stop method in the StandardHostDeployer class

清單 18.15:StandardHostDeployer 類中的 stop 方法



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);
    }
}

Summary

Deployers are components for deploying and installing web applications. A deployer is represented by the org.apache.catalina.Deployer interface. The StandardHost class implements Deployer to make it a special container to which web applications can be deployed. The StandardHost class delegates the tasks of deploying and installing applications to a helper class, org.apache.catalina.core.StandardHostDeployer. The StandardHostDeployer class provides the code that performs the task of deploying and installing applications, as well as starting and stopping a context.

部署器是用於部署和安裝Web應用程序的組件。

一個部署器由org.apache.catalina.Deployer接口表示。

StandardHost類實現了Deployer接口,使其成為一個特殊的容器,可以部署Web應用程序。

StandardHost類將部署和安裝應用程序的任務委託給一個輔助類org.apache.catalina.core.StandardHostDeployer。

StandardHostDeployer類提供了執行部署和安裝應用程序的代碼,以及啓動和停止上下文的任務。

user avatar pannideshoutao Avatar nianqingyouweidenangua Avatar xiongshihubao Avatar beishangdeyadan Avatar lijiahui_5f4488326fd1b Avatar huan1993 Avatar ryan_5fd1bc9a06259 Avatar wangqingsheng Avatar zhao_59106344e870e Avatar
Favorites 9 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.