zoukankan      html  css  js  c++  java
  • tomcat源码阅读_代码篇4

    StandardServer类:

    该类的签名如下:

    public final class StandardServer     implements Lifecycle, Server, MBeanRegistration

    该类实现了Lifecycle, Server, MBeanRegistration接口。

    Lifecycle接口是Catalina的组件的通用声明周期方法的接口,组件可以选择实现该接口。该接口定义了声明周期统一启动停止机制。方法定义如下:

    void addLifecycleListener(LifecycleListener listener)
               Add a LifecycleEvent listener to this component.
    LifecycleListener[] findLifecycleListeners()
               Get the lifecycle listeners associated with this lifecycle.
    void removeLifecycleListener(LifecycleListener listener)
               Remove a LifecycleEvent listener from this component.
    void start()
               Prepare for the beginning of active use of the public methods of this component.
    void stop()
               Gracefully terminate the active use of the public methods of this component.

    另外,还是用静态变量定义了一些常量:

    如:   

    /**
         * The LifecycleEvent type for the "component init" event.
         */
        public static final String INIT_EVENT = "init";

    Server接口表示整个Catalina servlet容器,它的属性代表了整个servlet容器的属性,一个Server可以有多个service,以及顶层命名资源集。

    该接口的实现要在指定端口上建立一个Server socket,是用其来监测连接,收到连接后首先需要跟关闭指令进行比较,如果是关闭指令则关闭服务。否则继续服务。

    MBeanRegistration 接口:

    该接口表示可以由 MBean 实现,以便在向 MBean 服务器注册或从其注销之前和之后执行操作。

    void postDeregister()
               允许 MBean 在已从 MBean 服务器注销之后执行所需要的任何操作。
    void postRegister(Boolean registrationDone)
               允许 MBean 在被注册到 MBean 服务器或注销失败后执行任何所需要的操作。
    void preDeregister()
               允许该 MBean 在从 MBean 服务器注销之前执行它所需要的任何操作。
    ObjectName preRegister(MBeanServer server, ObjectName name)
               允许 MBean 在被注册到 MBean 服务器之前执行它所需要的任何操作。

    构造函数如下:

        public StandardServer() {

            super();
            ServerFactory.setServer(this);//设置ServerFactory里的Server对象

            globalNamingResources = new NamingResources();//命名资源,这个类后面再看~~
            globalNamingResources.setContainer(this);//设置命名资源的容器

            if (isUseNaming()) {
                if (namingContextListener == null) {
                    namingContextListener = new NamingContextListener();
                    addLifecycleListener(namingContextListener);
                }
            }

        }

    addService方法   

    public void addService(Service service) {

            service.setServer(this);

            synchronized (services) {
                Service results[] = new Service[services.length + 1];
                System.arraycopy(services, 0, results, 0, services.length);
                results[services.length] = service;
                services = results;

                if (initialized) {
                    try {
                        service.initialize();
                    } catch (LifecycleException e) {
                        log.error(e);
                    }
                }

                if (started && (service instanceof Lifecycle)) {
                    try {
                        ((Lifecycle) service).start();
                    } catch (LifecycleException e) {
                        ;
                    }
                }

                // Report this property change to interested listeners
                support.firePropertyChange("service", null, service);
            }

        }

    这个方法的实现个人认为不太好,我尝试将其改为如下内容:

             List<Service>servList=Arrays.asList(services);
            servList.add(service);
            services=servList.toArray(new Service[0]);

    修改1:等整个修改完后会测试下修改后的性能

    await方法:

    public void await() {
            // Negative values - don't wait on port - tomcat is embedded or we just don't like ports
            if( port == -2 ) {
                // undocumented yet - for embedding apps that are around, alive.
                return;
            }
            if( port==-1 ) {
                while( true ) {
                    try {
                        Thread.sleep( 10000 );
                    } catch( InterruptedException ex ) {
                    }
                    if( stopAwait ) return;
                }
            }
           
            // Set up a server socket to wait on
            ServerSocket serverSocket = null;
            try {
                serverSocket =
                    new ServerSocket(port, 1,
                                     InetAddress.getByName("localhost"));
            } catch (IOException e) {
                log.error("StandardServer.await: create[" + port
                                   + "]: ", e);
                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) {
                    log.warn("StandardServer.accept security exception: "
                                       + ace.getMessage(), ace);
                    continue;
                } catch (IOException e) {
                    log.error("StandardServer.await: accept: ", e);
                    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();
                    expected += (random.nextInt() % 1024);
                }
                while (expected > 0) {
                    int ch = -1;
                    try {
                        ch = stream.read();
                    } catch (IOException e) {
                        log.warn("StandardServer.await: read: ", e);
                        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
                    log.warn("StandardServer.await: Invalid command '" +
                                       command.toString() + "' received");

            }

            // Close the server socket and return
            try {
                serverSocket.close();
            } catch (IOException e) {
                ;
            }

        }
    这段代码会创建一个ServerSocket,绑定到8005端口上,然后进入一个循环,在循环中会一直接受连接,直到收到关闭命令的时候,跳出循环,执行serverSocket.close()方法关闭服务器。

        public void removeService(Service service) {

            synchronized (services) {
                int j = -1;
                for (int i = 0; i < services.length; i++) {
                    if (service == services[i]) {
                        j = i;
                        break;
                    }
                }
                if (j < 0)
                    return;
                if (services[j] instanceof Lifecycle) {
                    try {
                        ((Lifecycle) services[j]).stop();
                    } catch (LifecycleException e) {
                        ;
                    }
                }
                int k = 0;
                Service results[] = new Service[services.length - 1];
                for (int i = 0; i < services.length; i++) {
                    if (i != j)
                        results[k++] = services[i];
                }
                services = results;

                // Report this property change to interested listeners
                support.firePropertyChange("service", service, null);
            }

        }

    这段代码实现的还是不错的~~~~...第二天我改变主意了,这段代码太复杂,可以简化下,我在standardService中进行修改,这里暂且不改了

    stop方法:

        public void stop() throws LifecycleException {

            // Validate and update our current component state
            if (!started)
                return;

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

            if (port == -1)
                stopAwait();

        }

    private LifecycleSupport lifecycle = new LifecycleSupport(this);

    这是负责生命周期的属性~~

  • 相关阅读:
    Linux守护进程
    sequel pro无法连接mysql服务器
    socket编程之并发回射服务器2
    Unix的I/O模型
    nginx.conf laravel 配置
    phpstudy使用PHP+nginx配置Laravel
    nginx配置文件分开配置
    centos安装composer
    linux下 设置php的环境变量 php: command not found
    laravel 安装
  • 原文地址:https://www.cnblogs.com/macula7/p/1960483.html
Copyright © 2011-2022 走看看