How Tomcat works--13 Host and Engine

Source: Internet
Author: User
Tags addchild constructor http request wrapper tomcat

Overview

The 2 topics to be discussed in this chapter are host and engine. If you need to deploy multiple contexts in a tomcat deployment, you need to use a host. Theoretically, a host is not required when there is only one context container, as described in the following Org.apache.catalina.Context interface:

"The parent container of the context container is usually the host, but there may be other implementations that can be ignored when it is not necessary."

In practice, however, a Tomcat deployment often requires a host. As for why, it will be seen in the section "Why host is required" later in this chapter.

The engine represents the entire Catalina Servlet engine. If used, it is usually at the highest level of the container level. Sub-containers that can be added to the engine are usually implemented in Org.apache.catalina.Host or Org.apache.catalina.Context. In a TOMCAT deployment, the engine container is used by default. In this deployment, the engine has a host, the default hosts.

This chapter discusses the classes associated with the Host and Engine interfaces. The Host-related standardhost, Standardhostmapper (TOMCAT4), and Standardhostvalve classes are introduced first. The next step is to demonstrate the case of host as a top-level container with a demo. Engine is the second topic discussed in this chapter and describes the Standardengine and Standardenginevalve classes. Next is the 2nd application demo in this chapter, which shows how to use the engine as a top-level container.

13.1 Host Interface

The host is represented by the Org.apache.catalina.Host interface. This interface inherits the Container interface, as shown in Listing13.1:

Listing 13.1:the Host Interface

Package Org.apache.catalina; Public interface Host extends Container {//-----------------------------------------------------Manifest Constant S/** * The ContainerEvent event type sent when a new alias was added * by <code>addalias () </code&
     gt;.


    */public static final String add_alias_event = "Addalias"; /** * The ContainerEvent event type sent when a old alias was removed * by <code>removealias () </code&gt
     ;.


    */public static final String remove_alias_event = "Removealias"; -------------------------------------------------------------Properties/** * Return the application root F  or this Host.
     This can is an absolute * pathname, a relative pathname, or a URL.


    */Public String getappbase ();  /** * Set The application root for this Host.
     This can is an absolute * pathname, a relative pathname, or a URL. * * @param appBase the new application root * *
    public void Setappbase (String appBase);  /** * Return The value of the auto deploy flag.
     If true, it indicates that * This host's child webapps should be discovred and automatically * deployed.


    */Public Boolean getautodeploy ();
     /** * Set The Auto Deploy flag value for this host.


    * * @param autodeploy The new auto Deploy flag */public void Setautodeploy (Boolean autodeploy);
     /** * Set the Defaultcontext * for new Web applications. * * @param defaultcontext the new defaultcontext * * public void Adddefaultcontext (Defaultcontext defaultcont


    EXT);
     /** * Retrieve the Defaultcontext for new Web applications.


    */Public Defaultcontext getdefaultcontext ();
     /** * Return The canonical, fully qualified, name of the virtual host * This Container represents.


    */Public String getName (); /** * Set The canonical, fully qualified, name of the VirtuAl Host * This Container represents. * * @param name Virtual host name * * @exception illegalargumentexception if name is null */Publi


    c void SetName (String name); ---------------------------------------------------------public Methods/** * Import the Defaultcontext con
     Fig into a Web application context. * * @param context Web application context to import default context */public void Importdefaultcontext (Con


    Text context);
     /** * Add An alias name that should is mapped to this same Host.


    * * @param alias The alias to be added */public void Addalias (String alias);  /** * Return The set of alias names for this Host.
     If none is defined, * a zero length array is returned.


    */Public string[] findaliases (); /** * Return The Context that would is used to process the specified * host-relative request URI, if any; otherwise return <code>null&Lt;/code>.


    * * @param uri Request URI to be mapped */public Context map (String URI);
     /** * Remove The specified alias name from the aliases for this Host.


* * @param alias alias name to be removed */public void Removealias (String alias); }

Of particular importance is the map () method, which returns the appropriate context to handle the request, and the implementation of the method can be found in the Standardhost class, which is discussed in the next section.

13.2 Standardhost Class

The Org.apache.catalina.core.StandardHost class is a standard implementation of the Host interface. This class inherits the Org.apache.catalina.core.ContainerBase class and implements the host and Deployer interfaces. The Deployer interface will be discussed in chapter 17th.

Similar to the Standardcontext and Standardwrapper classes, the constructor of the Standardhost class adds a base valve to its pipeline:

Public Standardhost () {
    super ();
    Pipeline.setbasic (New Standardhostvalve ());
}

As you can see, the base valve type is org.apache.catalina.core.StandardHostValve.

When started, such as the start () method is called, Standardhost adds 2 valves: Errorreportvalve and Errordispatchervalve. They are all in the Org.apache.catalina.valves package. The start () method of Standardhost in Tomcat4 is shown in Listing13.2:

Listing 13.2:the Start method of Standardhost

Public synchronized void Start () throws Lifecycleexception {
    //Set Error report valve
    if (errorreportvalveclass ! = null) && (!errorreportvalveclass.equals ("")) {
        try {
            valve valve = (valve) class.forname ( Errorreportvalveclass). newinstance ();
            Addvalve (valve);
        } catch (Throwable t) {
            log (sm.getstring ("Standardhost.invaliderrorreportvalveclass",
                Errorreportvalveclass ));
        }
    }
    Set Dispatcher Valve
    addvalve (New Errordispatchervalve ());
    Super.start ();
}

Note: In Tomcat5, the start () method is similar, and the difference is that the code that constructs the Jmx object is included, and JMX is discussed in chapter 20th.

The value of the Errorreportvalveclass is defined as follows:

Private String Errorreportvalveclass = "Org.apache.catalina.valves.ErrorReportValve";

For each request, the host's Invoke () method is called. Because the Stanardhost class does not implement the Invoke () method, it calls the Invoke () method of its parent class, the Containerbase class. The Invoke () method will instead invoke the Invoke () method of the Standardhost's underlying valve standardhostvalve. The Invoke () method of the standardhostvalve valve is discussed in the "Standardhostvalve class" subsection. In particular, the Invoke () method of Standardhostvalve calls the map () method of the Standardhost class to obtain a suitable context container for request processing. The map () method for Standardhost is shown in Listing13.3:

Listing 13.3:the Map method in the Standardhost class

Public Context map (String uri) {if (Debug > 0) log ("Mapping request uri '" + uri + "'");

        if (URI = = null) return (NULL); Match on the longest possible context path prefix if (Debug > 1) log ("Trying the longest conte
        XT path prefix ");
        Context context = NULL;
        String Mapuri = URI;
            while (true) {context = (context) findchild (Mapuri);
            if (context = null) break;
            int slash = Mapuri.lastindexof ('/');
            if (Slash < 0) break;
        Mapuri = mapuri.substring (0, Slash); }//If no Context matches, select the default context If (Context = = null) {If (Debug >
            1) log ("Trying The default context");
        Context = (context) Findchild (""); }//complain if no Context has been selected if (Context = = null) {log (Sm.getstring ("Standardhost.mappingerror", Uri));
        return (NULL); }//Return the mapped Context (if any) if (Debug > 0) log ("mapped to Context" + Contex
        T.getpath () + "'");

    return (context); }

Note In Tomcat4, the Containerbase class also declares a map () method with the following signature:

Public Container Map (Request request, Boolean update);

In Tomcat4, the Standardhostvavle Invoke () method calls Containerbase's Map () method, which in turn calls the map () method of Standardhost. In Tomcat5, there is no mapper component, and the appropriate context is obtained from the request object.

13.3 Standardhostmapper class

In Tomcat4, the parent class of Standardhost Containerbase creates a default mapper by calling the Adddefaultmapper () method in the Start () method. The type of the default mapper is specified by the Mapperclass property. The following is the Adddefaulstmapper () method of Containerbase:

protected void Adddefaultmapper (String mapperclass) {
    //Do we need a default Mapper?
    if (Mapperclass = = null)
        return;
    if (Mappers.size () >= 1)
        return;
    Instantiate and add a default Mapper
    try {
        Class clazz = Class.forName (mapperclass);
        Mapper Mapper = (Mapper) clazz.newinstance ();
        Mapper.setprotocol ("http");
        Addmapper (mapper);
    } catch (Exception e) {
        log (sm.getstring ("Containerbase.adddefaultmapper", Mapperclass), E);
    }
}

Standardhost defines the Mapperclass variable as follows:

Private String Mapperclass = "Org.apache.catalina.core.StandardHostMapper";

In addition, the start () method of the Standardhost class is guaranteed to create a default mapper at its last Call, Super.start ().

Note: Standardcontext in TOMCAT4 uses a slightly different method to create a default mapper. It does not call Super.start () in the Start () method. Instead, the start () method of Standardcontext calls Adddefaultmapper () to pass the Mapperclass variable.

The most important thing in Standardhostmapper is the map () method, the following is its implementation:

Public Container Map (Request request, Boolean update) {
    //have this Request already been mapped?
    if (Update && (request.getcontext () = null))
        return (Request.getcontext ());
    Perform mapping on our request URI
    String uri = ((httprequest) request). Getdecodedrequesturi ();
    Context context = Host.map (URI);
    Update the request (if requested) and return the selected Context
    if (update) {
        Request.setcontext (context); 
  if (context! = null)
        ((HttpRequest) request). Setcontextpath (Context.getpath ());
    Else
        ((HttpRequest) request). Setcontextpath (null);
    }
    return (context);
}

Note that the map () method simply calls the Host's map () method.

13.4 Standardhostvalve Class

The Org.apache.catalina.core.StandardHostValve class is the base valve for standardhost. When there is an HTTP request, its invoke () method is called, code such as listing 13.4:

Listing 13.4:the Invoke method of Standardhostvalve

public void invoke (Request request, Response Response, Valvecontext valvecontext) throws IO Exception, Servletexception {//Validate the request and Response object types if (! (
            Request.getrequest () instanceof HttpServletRequest) | | ! (Response.getresponse () instanceof HttpServletResponse))     {return;
        Note-not much else we can do generically}//Select the Context to is used for this Request
        Standardhost host = (standardhost) getcontainer ();
        Context context = (context) Host.map (request, true); if (context = = null) {((HttpServletResponse) Response.getresponse ()). Senderror (Httpservletre Sponse.
            Sc_internal_server_error, sm.getstring ("Standardhost.nocontext"));
        Return }//Bind the context CL to the current thread Thread.CurrentThread (). Setcontextclassloader ( Context.getloader (). getClassLoader ()); Update the session last access time to our session (if any) httpservletrequest Hreq = (httpservletrequest) req
        Uest.getrequest ();
        String sessionId = Hreq.getrequestedsessionid ();
            if (sessionId! = null) {Manager manager = Context.getmanager ();
                if (manager = NULL) {Session session = Manager.findsession (SESSIONID);
            if (session! = NULL) && session.isvalid ()) session.access ();

    }}//Ask This Context to process this request Context.invoke (request, response); }

Call Standardhost's Map () method in the Invoke () method in Tomcat4 to get an appropriate context:

Select the Context to is used for this Request
standardhost host = (standardhost) getcontainer ();
Context context = (context) Host.map (request, true);

Note: A roundtrip process is required to get the upper and lower objects. The map () method receives 2 parameters, which are in containerbase. The Containerbase class then finds the appropriate mapper in its sub-object (here is the Standardhost object) and calls its map () method.

The Invoke () method resolves a Session object and calls its access () method to update its last access time. The following is the access () method implementation in the Org.apache.catalina.session.StandardSession class:

public void Access () {
    this.isnew = false;
    This.lastaccessedtime = This.thisaccessedtime;
    This.thisaccessedtime = System.currenttimemillis ();
}

Finally, the Invoke () method invokes the Invoke () method of the context container, allowing the context to handle the request.

13.5 Why host is required

A tomcat deployment must have a host if the context is configured using Contextconfig. The reasons are as follows:

Contextconfig needs to apply the location of the file Web. XML, which tries to open the file in the Applicationconfig () method, and the following is a fragment of the method:

Synchronized (webdigester) {
    try {
        url url =
        servletcontext.getresource (constants.applicationwebxml);
        InputSource is = new InputSource (Url.toexternalform ());
        Is.setbytestream (stream);
        ...
        Webdigester.parse (is);
        ...

Constants.applicationwebxml defines the relative address of the/web-inf/web.xml file, ServletContext is a An object of type Org.apache.catalina.core.ApplicationContext (it implements Javax.servlet.ServletContext).

The following is the GetResource () method in the ApplicationContext class:

Public URL getresource (String path) throws Malformedurlexception {
    DirContext resources = context.getresources ();
    if (resources = null) {
        String FullPath = context.getname () + path;
        This is the problem. Host must not is null
        String hostName = Context.getparent (). GetName ();

The last line clearly indicates that the parent container (host) of the context is required, if configured with Contextconfig. In the 15th chapter, we will explain how to parse the Web. xml file. Simply put, unless you write the Contextconfig class yourself, you must have a host.

13.6 Application Demo1

The first application demo in this chapter demonstrates how to use a host as a top-level container. The program consists of 2 classes: The Ex13.pyrmont.core.SimpleContextConfig and the Ex13.pyrmont.startup.Bootstrap1 class. The Simplecontextconfig class is the same as in the 11th chapter, and the Boostrap2 class is shown in Listing13.5:

Listing 13.5:the Bootstrap1 Class

Package ex13.pyrmont.startup;
Explain Host import ex13.pyrmont.core.SimpleContextConfig;
Import Org.apache.catalina.Connector;
Import Org.apache.catalina.Context;
Import Org.apache.catalina.Host;
Import org.apache.catalina.Lifecycle;
Import Org.apache.catalina.LifecycleListener;
Import Org.apache.catalina.Loader;
Import Org.apache.catalina.Wrapper;
Import Org.apache.catalina.connector.http.HttpConnector;
Import Org.apache.catalina.core.StandardContext;
Import Org.apache.catalina.core.StandardHost;
Import Org.apache.catalina.core.StandardWrapper;


Import Org.apache.catalina.loader.WebappLoader; Public final class Bootstrap1 {public static void main (string[] args) {//invoke:http://localhost:8080/app1/primit
    Ive or Http://localhost:8080/app1/Modern system.setproperty ("Catalina.base", System.getproperty ("User.dir"));

    Connector Connector = new HttpConnector ();
    Wrapper wrapper1 = new Standardwrapper ();
    Wrapper1.setname ("Primitive"); Wrapper1.setservletclass ("Primitiveservlet ");
    Wrapper wrapper2 = new Standardwrapper ();
    Wrapper2.setname ("modern");

    Wrapper2.setservletclass ("Modernservlet");
    Context context = new Standardcontext ();
    Standardcontext ' s Start method adds a default mapper Context.setpath ("/app1");

    Context.setdocbase ("App1");
    Context.addchild (Wrapper1);

    Context.addchild (WRAPPER2);
    Lifecyclelistener listener = new Simplecontextconfig ();

    ((Lifecycle) context). Addlifecyclelistener (listener);
    Host host = new Standardhost ();
    Host.addchild (context);
    Host.setname ("localhost");

    Host.setappbase ("WebApps");
    Loader Loader = new Webapploader ();
    Context.setloader (loader);
    Context.addservletmapping (pattern, name);
    Context.addservletmapping ("/primitive", "Primitive");

    Context.addservletmapping ("/modern", "modern");
    Connector.setcontainer (host);
      try {connector.initialize ();
      ((Lifecycle) connector). Start (); ((Lifecycle) host). Start();
      Make the application wait until we press a key.
      System.in.read ();
    ((Lifecycle) host). Stop ();
    } catch (Exception e) {e.printstacktrace (); }
  }
}

13.6.1 Running Demo

Under Windows, you can run the program under the working directory by entering the following command:

Java-classpath./lib/servlet.jar;. /lib/commons-collections.jar;. /lib/commons-digester.jar;. /
Ex13.pyrmont.startup.Bootstrap1

You need to use semicolons to separate two libraries under Linux

Java-classpath./lib/servlet.jar:./lib/commons-collections.jar:./lib/commons-digester.jar:./
Ex13.pyrmont.startup.Bootstrap1

You can call Primitiveservlet and Modernservlet using the following URLs:

Http://localhost:8080/app1/Primitive
Http://localhost:8080/app1/Modern

13.7 Engine Interface

The Org.apache.catalina.Engine interface is used to represent an engine. The engine represents the entire Catalina Servlet engine. When we want to support multiple virtual hosts, we need an engine that actually uses the Tomcat deployment. Engine interface as shown in Listing 13.6:

Listing 13.6:the Engine Interface

Public interface Engine extends Container {//-------------------------------------------------------------Propert
     IES/** * Return The default hostname for this Engine.


    */Public String getdefaulthost ();
     /** * Set The default hostname for this Engine.


    * * @param defaulthost The new default host */public void Setdefaulthost (String defaulthost);
     /** * Retrieve The Jvmrouteid for this engine.


    */Public String getjvmroute ();
     /** * Set The Jvmrouteid for this engine. * * @param jvmrouteid the (new) JVM Route ID.
     Each Engine within a cluster * must has a unique JVM Route ID.


    */public void Setjvmroute (String jvmrouteid);
     /** * Return The <code>Service</code> with which we is associated (if any).


    */Public Service getService ();
     /** * Set The <code>Service</code> with which we is associated (if any). * * @paRAM Service The service that is owns this Engine */public void Setservice (service service);
     /** * Set the Defaultcontext * for new Web applications. * * @param defaultcontext the new defaultcontext * * public void Adddefaultcontext (Defaultcontext defaultcont


    EXT);
     /** * Retrieve the Defaultcontext for new Web applications.


    */Public Defaultcontext getdefaultcontext (); ---------------------------------------------------------public Methods/** * Import the Defaultcontext con
     Fig into a Web application context. * * @param context Web application context to import default context */public void Importdefaultcontext (Con


Text context); }

You can set the default host or context for the engine. Note engines are also associated with services (service). Services related content will be introduced in chapter 14th.

13.8 Standardengine class

Class Org.apache.catalina.core.StandardEngine is the standard implementation of the Engine interface, and the Standardengine class is relatively small compared to Standardcontext and Standardhost. When initializing, the Standardengine class needs to add a basic valve, the following is the class constructor:

Public Standardengine () {
    super ();
    Pipeline.setbasic (New Standardenginevalve ());
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.