Tomcat源码分析之Catalina

Catalina

全类名:org.apache.catalina.startup.Catalina

catalina.load(args)

执行Bootstrap类的load(args)方法,会执行catalina.load(args)方法。

catalina.load(args),代码

/**
     * Start a new server instance.
     */
    public void load() {

        // 省略

        // Parse main server.xml,解析server.xml
        parseServerXml(true);
        Server s = getServer();
        if (s == null) {
            return;
        }

        getServer().setCatalina(this);
        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());

        // Stream redirection
        initStreams();

        // Start the new server 启动server
        try {
            getServer().init();
        } catch (LifecycleException e) {
            if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
                throw new java.lang.Error(e);
            } else {
                log.error(sm.getString("catalina.initError"), e);
            }
        }

        // 省略
    }

核心两件事情

1)parseServerXml(true),解析server.xml,生成相应的对象,比如Server、Service、Connector、Engine、Host等等;

解析server.xml,是由Digester完成的。在创建Digester的时候会生成每一个标签节点和类的映射规则,也会生成标签和子标签的关系规则,再根据这些规则,调用Digester的parse方法,生成对应的对象。Server、Service、Connector、Engine等对象都是在这个阶段生成的。

部分代码:

// 获取server.xml
ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()
// 创建 Digester 对象
Digester digester = start ? createStartDigester() : createStopDigester();
InputStream inputStream = resource.getInputStream();
InputSource inputSource = new InputSource(resource.getURI().toURL().toString());
inputSource.setByteStream(inputStream);
// 将当前catalina传入作为起始对象
digester.push(this);   
// 开始解析
digester.parse(inputSource);

2)getServer().init(),初始化server,调用Server的init方法。

catalina.start(args)

执行Bootstrap类的start(args)方法,会执行catalina.start(args)方法。

catalina.start(args),简化代码

/**
     * Start a new server instance.
     */
    public void start() {

        // 省略

        // Start the new server 启动server
        try {
            getServer().start();
        } catch (LifecycleException e) {
            log.fatal(sm.getString("catalina.serverStartFail"), e);
            try {
                getServer().destroy();
            } catch (LifecycleException e1) {
                log.debug("destroy() failed for failed Server ", e1);
            }
            return;
        }

        // 省略

        // Register shutdown hook 注册一个shutdown钩子
        if (useShutdownHook) {
            if (shutdownHook == null) {
                shutdownHook = new CatalinaShutdownHook();
            }
            Runtime.getRuntime().addShutdownHook(shutdownHook);

            // 省略
        }

        if (await) {
            // 阻塞线程保证主线程活跃,内部创建一个ServerSocket,监听server.xml配置的shutdown端口8005
            await();
            stop();
        }
    }

核心两件事:

1)getServer().start(),启动server,调用server的start方法

2)注册shutdown钩子以及创建ServerSocket监听shutdown指令

shutdown钩子:如果非守护线程都退出或者System.exit方法执行,或者虚拟机被终止了,都会触发这个钩子,从而停止tomcat。

ServerSocket监听:监听server.xml配置的shutdown端口8005,并且接收到的指令是SHUTDOWN,方法不会再阻塞,讲直接调用stop方法。

await和stop方法都是调用的server里的await和stop

server的await简化代码:

// 接收连接时间
socket = serverSocket.accept();
stream = socket.getInputStream();
while (expected > 0) {
  ch = stream.read();
	command.append((char) ch);
}
boolean match = command.toString().equals(shutdown);

本地启动之后执行:telnet localhost 8005

再输入:SHUTDOWN

则服务将停止。

catalina的stop简化代码:

/**
     * Stop an existing server instance.
     */
    public void stop() {

        // 省略

        // Shut down the server
        try {
            Server s = getServer();
            LifecycleState state = s.getState();
            if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
                    && LifecycleState.DESTROYED.compareTo(state) >= 0) {
                // Nothing to do. stop() was already called
            } else {
                // 停止实例
                s.stop();
                s.destroy();
            }
        } catch (LifecycleException e) {
            log.error(sm.getString("catalina.stopError"), e);
        }

    }

catalina.start(args)执行完,服务启动。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值