tomcat源码阅读_代码篇4

我只是一个虾纸丫 提交于 2020-04-07 13:19:14

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

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!