How Tomcat Works学习笔记<十三>

来源:互联网 发布:unity3d api 编辑:程序博客网 时间:2024/04/27 16:35
 

Server和Service

         在前面的章节中Catalina已经有了连接器(Connector)和容器(Container),但是还缺少一种好的启动和停止Servlet容器的机制,Server和Service能很好的解决这个问题。

Server

         org.apache.catalina.Server接口表示完整的Servlet容器和相关的其他组件,提供了优雅启动和停止整个系统的机制,有了它以后没有必要再分别去启动连接器和容器。

         当你启动一个Server的时候,它会启动在其内的所有组件,然后等待识别的shutdown命令,一旦通过指定的端口发送了shutdown命令,被server接收到以后它将停止所有的组件,Server定义如下:

         public interface Server {

        public String getInfo();

        public NamingResources getGlobalNamingResources();

        public void setGlobalNamingResources(NamingResources globalNamingResources);

        public int getPort();

        public void setPort(int port);

        public String getShutdown();

        public void setShutdown(String shutdown);

        public void addService(Service service);

        public void await();

        public Service findService(String name);

        public Service[] findServices();

        public void removeService(Service service);

        public void initialize()throws LifecycleException;

}

通过addService方法可以下Server添加Service对象。

StandardServer

    StandardServer是Server接口的标准实现,其中最重要的是他的shutdown机制,同时也包括一些解析Server配置(server.xml)的方法。

    一个Server包括一个或多个Service,提供了addService和removeService方法,作为组件,Server也实现了生命周期的相关功能,提供了initialize、start、stop和await方法。

initialize方法

         initialize方法会初始化Service并添加到Server实例当中:

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

        }

}

在StandardServer中增加了initialized变量,防止重复初始化Server。

start方法

         start方法会启动所有的Service,从而启动其它组件,像连接器、容器等:

         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 (services) {

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

                if (services[i] instanceof Lifecycle)

                    ((Lifecycle) services[i]).start();

            }

        }

        // Notify our interested LifecycleListeners

        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

}

在StandardServer中添加了started变量控制重复调用start方法。

stop方法

         stop方法停止server:

         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)

                ((Lifecycle) services[i]).stop();

        }

        // Notify our interested LifecycleListeners

        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

    }

         stop方法会停止所有service,并把started改为false,从而可以再次启动Server。

await方法

         await方法的职责是停止整个Tomcat部署:

         public void await() {

        // Set up a server socket to wait on

        ServerSocket serverSocket = null;

        try {

            serverSocket =

                new ServerSocket(port, 1,

                                 InetAddress.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 connection

            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: "+ ace.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; // Cut off to 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();

                } catch (IOException e) {

                    System.err.println("StandardServer.await: read: " + e);

                    e.printStackTrace();

                    ch = -1;

                }

                if (ch < 32)  // Control character or EOF terminates loop

                    break;

                command.append((char) ch);

                expected--;

            }

 

            // Close the socket now that 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 '" +

                                   command.toString() + "' received");

        }

 

        // Close the server socket and return

        try {

            serverSocket.close();

        } catch (IOException e) {

            ;

        }

}

await方法会监听来自客户端的命令,一旦发现传来shutdown的命令,将会停止这个Tomcat部署。

Service

         org.apache.catalina.Service接口表示一个服务,一个服务可以包括一个容器和多个连接器,所有的连接器都必须分配给容器,Service接口定义如下:

         public interface Service {

        public Container getContainer();

        public void setContainer(Container container);

        public String getInfo();

        public String getName();

        public void setName(String name);

        public Server getServer();

        public void setServer(Server server);

        public void addConnector(Connector connector);

        public Connector[] findConnectors();

        public void removeConnector(Connector connector);

        public void initialize()throws LifecycleException;

}

StandardService

         StandardService是Service的标准实现类,包括两种类型的组件:连接器和容器

         通过setContainer方法为Service分配容器:

         public void setContainer(Container container) {

        Container oldContainer = this.container;

        if ((oldContainer != null) && (oldContainerinstanceof Engine))

            ((Engine) oldContainer).setService(null);

        this.container = container;

        if ((this.container != null) && (this.container instanceof Engine))

            ((Engine) this.container).setService(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) {

                ;

            }

        }

        // Report this property change to interested listeners

        support.firePropertyChange("container", oldContainer, this.container);

}

通过addConnector方法添加连接器:

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 {

                    ((Lifecycle) connector).start();

                } catch (LifecycleException e) {

                    ;

                }

            }

            // Report this property change to interested listeners

            support.firePropertyChange("connector", null, connector);

        }

 }

    通过removeConnector方法移除连接器:

    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) connectors[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 this property change to interested listeners

            support.firePropertyChange("connector", connector, null);

        }

}

原创粉丝点击