How Tomcat works--14 server and Service

Source: Internet
Author: User
Tags stringbuffer

Overview

In the previous chapters you've seen how to initialize connectors and containers and associate them as servlet containers. There is only one connector ahead that serves HTTP requests through port 8080. We cannot add another connector to handle requests such as HTTPS.

In addition, all of the preceding demo programs lacked one thing: the mechanism to start and stop the Servlet container well. In this chapter, we will provide this mechanism as well as some other ancillary components: servers (server) and services (service).

14.1 Server Interface

The Org.apache.catalina.Server interface represents the entire Catalina Servlet container and includes other components. A server is quite useful because it provides an elegant mechanism to start and stop the entire system. You do not have to start the connectors and containers individually.

The following describes how the startup and stop mechanisms work. When the server starts, it starts all the components inside it, and then waits indefinitely for the shutdown command. If you want to shut down the system, we send a close command to the specified port. When the server receives the correct shutdown directive, it stops the service for all components.

The server also uses a different component, a service, used to hold components, such as a container or a number of
Connectors. Services are described in the service section of this chapter.

The Server interface is shown as Listing14.1.

Listing 14.1:the Server Interface

Package Org.apache.catalina;

Import org.apache.catalina.deploy.NamingResources;
     Public interface Server {//-------------------------------------------------------------Properties/** * Return descriptive information about this Server implementation and * the corresponding version
     Mat * <CODE><DESCRIPTION>/<VERSION></CODE>.


    */Public String getInfo ();
     /** * Return to the global naming resources.


    * * Public namingresources getglobalnamingresources ();
     /** * Set the global naming resources.
        * * @param namingresources The new global naming resources */public void setglobalnamingresources


    (Namingresources globalnamingresources);
     /** * Return the port number we listen to the shutdown commands.


    * * public int getport ();
     /** * Set The port number we listen to the shutdown commands. * * @param port the NEW Port number */public void setport (int port);
     /** * Return the SHUTDOWN command string we are waiting for.


    */Public String getshutdown ();
     /** * Set The shutdown command we are waiting for.


    * * @param shutdown the new shutdown command */public void Setshutdown (String shutdown); ---------------------------------------------------------public Methods/** * Add A new Service to the set
     of defined Services.


    * * @param service The service to be added/public void AddService (service service);
     /** * Wait until a proper shutdown command are received, then return.


    * * public void await (); /** * Return the specified Service (if it exists);
     otherwise return * <CODE>NULL</CODE>.


    * @param name Name of the service to be returned/public service Findservice (String name); /** * Return the set of Services defined within THis Server.


    * * Public service[] findservices ();
     /** * Remove The specified Service from the set associated to this * Server.

    * * @param service the service to be removed/public void RemoveService (service service); /** * Invoke a pre-startup initialization.
     This are used to allow connectors * to bind to restricted ports under Unix operating environments.
     * * @exception lifecycleexception If This server is already initialized.
* * public void Initialize () throws lifecycleexception; }

Property shutdown is used to hold a command string that stops the service. The property port is the port on which the server waits to receive the shutdown command. You can call the server's AddService () method to add the service to the server. Use the RemoveService () method to remove the service. Findservices () returns all services in the server. The Initialize () method contains code that needs to be executed before startup.

14.2 Standardserver class

The Org.apache.catalina.core.StandardServer class is a standard implementation of the server (server-based). We will pay special attention to the most important feature of this class: the shutdown mechanism. There is no discussion about how to configure the server via Server.xml. If you are interested, you can read it yourself, it is not difficult to understand.

A server can have 0 or more services, and the Standardserver class provides implementations of the AddService (), RemoveService (), Findservices () methods.

There are 4 other ways of life-cycle Related: Initialize (), start (), Stop (), and await (). Similar to other components, initialize and start a server. You can then use the await () method and the Stop () method. The await () method waits until it receives a 8085 port (or other port) shutdown instruction. When the await () method returns, the Stop () method executes all child components. In the demo of this chapter, we can see how to implement the shutdown mechanism.

About Initialize (), start (), the contents of the Stop () and await () methods are discussed in the following sub-section.

14.3.1 Initialize () method

The Initialize () method initializes the services added to the server instance, Standardserver Initialize () methods such as Listing14.2:

Listing 14.2:the Initialize Method

public void Initialize () throws Lifecycleexception {
    if (initialized)
        throw new Lifecycleexception ( Sm.getstring ("StandardServer.initialize.initialized"));
    initialized = true;
    Initialize our defined Services for
    (int i = 0; i < services.length; i++) {
        services[i].initialize ();
    }
}

Note that the method uses a variable named initialized to avoid starting the server multiple times. In Tomcat5, the Initialize () method is similar, but includes the relevant code for JMX. The Stop () method does not reset the value of the initialized, so the initialized () method is not called again when the server is stopped and started again.

14.3.2 Start () method

You can use the start () method to start a server, and the implementation of the Standardserver start () method will start all services and their associated components, such as connectors and containers. Listing14.3 shows the Start () method:

Listing 14.3:the Start method

public void Start () throws Lifecycleexception {
    //Validate and update our current component state
    if (started) 
  throw New Lifecycleexception (sm.getstring ("standardServer.start.started"));
    Notify our interested lifecyclelisteners
    lifecycle.firelifecycleevent (before_start_event, null);
    Lifecycle.firelifecycleevent (start_event, null);
    started = true;
    Start our defined Services
    synchronized {for
        (int i = 0; i < services.length; i++) {
            if (SE Rvices[i] instanceof Lifecycle)
                ((Lifecycle) services[i]). Start ();
    Notify our interested lifecyclelisteners
    lifecycle.firelifecycleevent (after_start_event, null);
}

The method uses a started Boolean variable to prevent a server from being started two times. The value of the variable is reset in the Stop () method.

14.3.3 Stop () method

The Stop () method is used to stop a server, as shown in Listing14.4:

Listing 14.4:the Stop method

public void Stop () throws Lifecycleexception {
    //Validate and update our current component state
    if (!started) 
  throw New Lifecycleexception (sm.getstring ("standardServer.stop.notStarted"));
    Notify our interested lifecyclelisteners
    lifecycle.firelifecycleevent (before_stop_event, null);
    Lifecycle.firelifecycleevent (stop_event, null);
    started = false;
    Stop our defined Services for
    (int i = 0; i < services.length i++) {
        if (services[i) instanceof Lifecycle) c10/> ((Lifecycle) services[i]). Stop ();
    Notify our interested lifecyclelisteners
    lifecycle.firelifecycleevent (after_stop_event, null);
}

Call the Stop () method to stop all services and reset the value of the started variable so that the server can be started again.

14.3.4 await () method

Await () is responsible for the stop mechanism for the entire TOMCAT deployment, and its code is shown as Listing14.5:

Listing 14.5:the await method

/** * Wait until a proper shutdown command are received, then return.
        */public void await () {//Set up a server socket to serversocket serversocket = null; try {serversocket = new ServerSocket (port, 1, Inetaddres
        S.getbyname ("127.0.0.1"));
                               catch (IOException e) {System.err.println ("standardserver.await:create[" + port
            + "]:" + e);
            E.printstacktrace ();
        System.exit (1); }//Loop waiting for a connection and a valid command while (TRUE) {//wait for the next C
            onnection socket socket = NULL;
            InputStream stream = null;
                try {socket = serversocket.accept ();  Socket.setsotimeout (10 * 1000);
            Ten seconds stream = Socket.getinputstream (); catch (Accesscontrolexception ace) {System.err.println ("standardserver.accept Security Exception:" + AC
                E.getmessage ());
            Continue
                catch (IOException e) {System.err.println ("StandardServer.await:accept:" + e);
                E.printstacktrace ();
            System.exit (1);
            //Read A set of characters from the socket stringbuffer command = new StringBuffer (); int expected = 1024;
                    Avoid DoS attack while (expected < shutdown.length ()) {if (random = null)
                Random = new Random (System.currenttimemillis ());
            Expected + + (Random.nextint ()% 1024);
                while (Expected > 0) {int ch =-1;
                try {ch = stream.read (); The catch (IOException e) {System.err.println ("StandardServer.await:reaD: "+ E);
                    E.printstacktrace ();
                ch =-1;
                if (Ch <)//control character or EOF terminates the loop break;
                Command.append ((char) ch);
            expected--;
            }//Close the socket now, we are done with it try {socket.close ();
            catch (IOException e) {;
            /match against our command string Boolean Match = Command.tostring (). Equals (shutdown);
            if (match) {break; else System.err.println ("StandardServer.await:Invalid command" + C

        Ommand.tostring () + "' Received");
        }//Close the server socket and return try {serversocket.close ();
        catch (IOException e) {; }

    }

Method await () creates a ServerSocket object on port 8085 and calls its accept () method in the while loop. The Accept () method only accepts information from Port 8085. It will receive the information to match the shutdown command, if the match out of the loop to turn off the socketserver, if it does not match the continue while loop waiting for another command.

14.3 Service Interface

The Org.apache.catalina.Service interface is used to represent a service. A service can have a container and multiple connectors. We can add multiple connectors and associate them with the container. The service interface is shown as Listing14.6:

Listing 14.6:the Service Interface

Public interface Service {//-------------------------------------------------------------Properties/**  * Return the <code>Container</code> handles requests to all * <code>Connectors</code>
     Associated with the This Service.


    * * Public Container getcontainer (); /** * Set The <code>Container</code> that handles requests to all * <code>connectors</code
     > associated with the This Service.


    * * @param container The new container */public void Setcontainer (Container container); /** * Return descriptive information about this Service implementation and * The corresponding version number, I
     n the format * &LT;CODE&GT;&AMP;LT;DESCRIPTION&AMP;GT;/&AMP;LT;VERSION&AMP;GT;&LT;/CODE&GT;.


    */Public String getInfo ();
     /** * Return the name of this Service.


    */Public String getName ();
     /** * Set The name of this Service.
     ** @param name the new service name */public void SetName (String name);
     /** * Return the <code>Server</code> with which we are associated (if any).


    * * Public Server getserver ();
     /** * Set The <code>Server</code> with which we are associated (if any).


    * * @param server The server that owns this Service/public void Setserver (server server); ---------------------------------------------------------public Methods/** * Add A new Connector to the SE
     T of defined connectors, and associate it * with the This Service ' s Container.


    * * @param connector the connector to be added/public void AddConnector (connector connector);
     /** * Find and return the set of connectors associated with this Service.


    * * Public connector[] findconnectors ();  /** * Remove The specified Connector from the set associated to this * Service. The removed ConnEctor would also be disassociated to our * Container.

    * * @param connector the connector to be removed/public void Removeconnector (connector connector); /** * Invoke a pre-startup initialization.
     This are used to allow connectors * to bind to restricted ports under Unix operating environments.
     * * @exception lifecycleexception If This server is already initialized.

* * public void Initialize () throws lifecycleexception; }

14.4 Standardservice Class

The Org.apache.catalina.core.StandardService class is the standard implementation of the Service interface. The Initialize () method of the Standardservice class initializes all connectors added to the service. The class also implements the Org.apache.catalina.Lifecycle interface, so its start () method can start all connectors and containers.

14.4.1 containers and connectors

A Standardservice instance consists of two components: a container and multiple connectors. Multiple connectors enable Tomcat to serve a variety of protocols. One for processing HTTP protocol requests and another for processing HTTPS protocol requests.

The Standardservice class uses the container variable to hold the container instance and to hold all connectors with the connectors array:

Private Container Container = null;
Private Connector connectors[] = new Connector[0];

To associate a container with a service, you can use the Setcontainer () method as shown in the following Listing14.7:

Listing 14.7:the Setcontainer method

public void Setcontainer (Container Container) {Container oldcontainer = This.container; if ((Oldcontainer!= null) && (Oldcontainer instanceof Engine)) ((Engine) oldcontainer). Setservice (nul
        L);
        This.container = container; if ((This.container!= null) && (This.container instanceof Engine)) ((Engine) this.container). Setservi
        CE (this);
            if (Started && (this.container!= null) && (this.container instanceof Lifecycle)) {
            try {((lifecycle) this.container). Start ();
            catch (Lifecycleexception e) {;
                } synchronized (connectors) {for (int i = 0; i < connectors.length; i++)
        Connectors[i].setcontainer (This.container);
            } if (started && (oldcontainer!= null) && (oldcontainer instanceof Lifecycle)) {
              try {  ((lifecycle) oldcontainer). Stop ();
            catch (Lifecycleexception e) {; }//Interested listeners Support.firepropertychange ("container"

    , Oldcontainer, This.container); }

The container associated with this service is passed through the Setcontainer () method to each available connector object in this service, associating the container with each connector individual.

You can use the AddConnector () method to add connectors to the service. To remove a connector, you can use the Removeconnector () method. They are shown as Listing14.8 and Listing14.9 respectively:

Listing 14.8:the AddConnector method

public void AddConnector (Connector Connector) {synchronized (connectors) {Connector
        . Setcontainer (This.container);
        Connector.setservice (this);
        Connector results[] = new Connector[connectors.length + 1];
        System.arraycopy (connectors, 0, results, 0, connectors.length);
        Results[connectors.length] = connector;
        connectors = results;
            if (initialized) {try {connector.initialize ();
            }catch (lifecycleexception e) {e.printstacktrace (system.err); } if (started && (Connector instanceof Lifecycle)) {try {(LIFECYC
            Le) connector). Start ();
        }catch (Lifecycleexception e) {;} }///The interested listeners Support.firepropertychange ("connector", NULL, con
    Nector); }
}

Listing 14.9:the Removeconnector method

public void Removeconnector (Connector Connector) {synchronized (connectors) {Int J =-1;
                    for (int i = 0; i < connectors.length i++) {if (connector = = Connectors[i]) {
                    j = i;
                Break
            } if (J < 0) return; if (started && (Connectors[j] instanceof Lifecycle)) {try {(lifecycle) conn
                ECTORS[J]). Stop ();
                catch (Lifecycleexception e) {;
            } connectors[j].setcontainer (NULL);
            Connector.setservice (NULL);
            int k = 0;
            Connector results[] = new Connector[connectors.length-1]; for (int i = 0; i < connectors.length i++) {if (i!= j) results[k++] = Connectors
            [i];

            } connectors = results; REport to interested listeners Support.firepropertychange ("connector", connector, NULL); }

    }

The AddConnector () method initializes and starts all added connectors.

14.4.2 life cycle approach

The lifecycle (), start (), Stop (), and Initialize () methods are inherited from the lifecycle interface. The Initialize () method of each connector in this service is called in the Initialize () method, as shown in Listing14.10:

Listing 14.10:the Initialize Method of Standardservice

public void Initialize () throws Lifecycleexception {
    if (initialized)
        throw new Lifecycleexception ( Sm.getstring ("StandardService.initialize.initialized"));
    initialized = true;
    Initialize we defined connectors
    synchronized (connectors) {for
    (int i = 0; i < connectors.length; i++) { C7/>connectors[i].initialize ();

    }

The start () method is used to initiate the associated connectors and containers, as shown in Listing14.11:

Listing 14.11:the Start method

public void Start () throws Lifecycleexception {//Validate and update we component State if (ST
        arted) {throw new Lifecycleexception (sm.getstring ("standardService.start.started"));

        }//Notify Our interested lifecyclelisteners lifecycle.firelifecycleevent (before_start_event, NULL);
        System.out.println (sm.getstring ("StandardService.start.name", this.name));
        Lifecycle.firelifecycleevent (start_event, NULL);

        started = true;
                Start our defined Container (Container!= null) {synchronized (Container) {
                if (container instanceof Lifecycle) {(lifecycle) container). Start ();
            }}//Start our defined connectors second synchronized (connectors) { for (int i = 0; i < connectors.length i++) {if (Connectors[i] instanceof Lifecycle) ((lifecycle) connectors[i]). Start (); }//Notify Our interested lifecyclelisteners lifecycle.firelifecycleevent (after_start_event, n

    ULL); }

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.