Tomcat源码解析(二):server服务管理组件

前面一节博客说明了Tomcat中Catalina子模块的整体架构,Tomcat中最顶层容器为Server,所有其他组件都被其包含,而Server的关闭启动由Catalina管理,Server的默认实现类为StandardServer,其至少包含一个或者多个Service服务。

1、Server服务器管理组件

Server接口主要方法也是关于对Service服务的管理,以及等待管理端口。

public interface Server {
    // shutdown端口管理
    public int getPort();
    public void setPort(int port);
    // 服务组件管理
    public void addService(Service service);

    public void await();

    public Service[] findServices();

    public void removeService(Service service);
    // 初始化
    public void initialize()
    throws LifecycleException;
}
Server接口的默认实现类为StandardServer,查看其继承关系,还实现Lifecycle生命周期接口,Tomcat中基本大部分组件都实现该接口,统一生命周期管理,主要在组件创建和销毁动作之前进行必要的预处理操作。

StandardServer主要功能:

1、统一管理所有Service服务组件,包含初始化、启动和关闭等操作

2、主线程调用start启动容器后,阻塞等待shutdown关闭命令

由于StandardServer代码较多,不全部贴出,查看其重要属性

    // 生命周期工具类,委托管理
    private LifecycleSupport lifecycle = new LifecycleSupport(this);

    // 等待关闭命令端口
    private int port = 8005;

    // 相关联的所有Service服务组件
    private Service services[] = new Service[0];
    
    // 是否已经启动
    private boolean started = false;
    // 是否已经初始化
    private boolean initialized = false;
 
StandardServer管理器Service组件就存储在一个数组中,也没有想象中高大上......

Tomcat是通过配置文件server.xml来创建StandardServer实例的,所以StandardServer中许多方法是与server.xml配置文件相关。这里不做介绍。StandardServer中与容器生命周期相关的方法分别是initialize()方法、start()方法、stop()方法、await()方法,接下来主要对这几个方法介绍。

initialize()方法

    public void initialize()
    throws LifecycleException {
        // 防止初始化两次
        if (initialized)
            throw new LifecycleException (
                sm.getString("standardServer.initialize.initialized"));
        initialized = true;

        // 初始化所有Service组件
        for (int i = 0; i < services.length; i++) {
            services[i].initialize();
        }
    }

start()方法

    public void start() throws LifecycleException {
        // 不能重复启动
        if (started)
            throw new LifecycleException
                (sm.getString("standardServer.start.started"));
        // 触发BEFORE_START_EVENT事件,通知相关监听器
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        // 触发START_EVENT事件
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // 启动所有Service服务组件
        synchronized (services) {
            for (int i = 0; i < services.length; i++) {
                // 判断Service是否实现Lifecycle接口
                // start方法属于Lifecycle接口
                if (services[i] instanceof Lifecycle)
                    ((Lifecycle) services[i]).start();
            }
        }

        // 触发AFTER_START_EVENT事件
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }
stop()方法
    public void stop() throws LifecycleException {
        // Validate and update our current component state
        if (!started)
            throw new LifecycleException
                (sm.getString("standardServer.stop.notStarted"));

        // 触发相关事件,通知监听器
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        // started设置false 注:这里没有设置initialize为false
        started = false;

        // 依次关闭Service服务组件
        for (int i = 0; i < services.length; i++) {
            if (services[i] instanceof Lifecycle)
                ((Lifecycle) services[i]).stop();
        }

        // 触发相关事件,通知监听器
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

    }

await()方法

await()方法创建一个ServerSocket对象监听8005端口,并在while循环中一直等待连接,当指定端口接受到连接accept()才会返回,此时对比接受消息是否是shutdown,是就结束,否则继续监听。

主线程调用await()方法等待,唯一一个用户线程,其余Tomcat线程都是后台线程(Deamon),所以当await接受shutdown指令时,退出while循环,即主线程退出,随即Tomcat关闭。

    public void await() {
        // 默认端口8005
        ServerSocket serverSocket = new ServerSocket(port, 1,
                InetAddress.getByName("127.0.0.1"));

        // 循环serverSocket监听
        while (true) {
            // Wait for the next connection
            Socket socket = null;
            socket = serverSocket.accept();

            ......读取socket内容

            boolean match = command.toString().equals(shutdown);
            if (match) {
                // 如果是shutdown命令,退出
                break;
            } else
        }
    }

关于Service与Server的绑定关系,可以看下addService()方法,removeService()方法相似道理
    public void addService(Service service) {
        // 关联当前StandServer
        service.setServer(this);

        synchronized (services) {
            // 更新服务组件services
            Service results[] = new Service[services.length + 1];
            System.arraycopy(services, 0, results, 0, services.length);
            results[services.length] = service;
            services = results;
            // 如果Server已经初始化,则初始化当前Service
            if (initialized) {
                service.initialize();
            }
            // 如果Server已经启动,则启动当前Service
            if (started && (service instanceof Lifecycle)) {
                ((Lifecycle) service).start();
            }
        }
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值