首页 > 其他 > 详细

tomcat源码 分析 Catalina

时间:2018-12-08 21:41:26      阅读:134      评论:0      收藏:0      [点我收藏+]

通过查看分析启动脚本,发现最终调用的入口是org.apache.catalina.startup包下面的Bootstrap#main

public static void main(String args[]) {

    if (daemon == null) {
        // Don‘t set daemon until init() has completed
        Bootstrap bootstrap = new Bootstrap();
        try {
            // 初始化类加载器(这主要是为了要把开发者编写的各种组件应用(WAR 、EAR 等)部署到容器中,并实现组件应用之间的隔离),创建Catalina实例
            bootstrap.init();
        } catch (Throwable t) {
            handleThrowable(t);
            t.printStackTrace();
            return;
        }
        daemon = bootstrap;
    } else {
        // When running as a service the call to stop will be on a new
        // thread so make sure the correct class loader is used to prevent
        // a range of class not found exceptions.
        Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
    }

    try {
        String command = "start";
        if (args.length > 0) {
            command = args[args.length - 1];
        }

        if (command.equals("startd")) {
            args[args.length - 1] = "start";
            daemon.load(args);
            daemon.start();
        } else if (command.equals("stopd")) {
            args[args.length - 1] = "stop";
            daemon.stop();
        } else if (command.equals("start")) {
            daemon.setAwait(true);
            // 通过反射调用Catalina的load方法,加载server.xml配置、初始化Server
            daemon.load(args);
            // 通过反射调用Catalina的start方法,开启服务、初始化并开启一系列组件、子容器
            daemon.start();
            if (null == daemon.getServer()) {
                System.exit(1);
            }
        } else if (command.equals("stop")) {
            daemon.stopServer(args);
        } else if (command.equals("configtest")) {
            daemon.load(args);
            if (null == daemon.getServer()) {
                System.exit(1);
            }
            System.exit(0);
        } else {
            log.warn("Bootstrap: command \"" + command + "\" does not exist.");
        }
    } catch (Throwable t) {
        // Unwrap the Exception for clearer error reporting
        if (t instanceof InvocationTargetException &&
                t.getCause() != null) {
            t = t.getCause();
        }
        handleThrowable(t);
        t.printStackTrace();
        System.exit(1);
    }

}

 

类org.apache.catalina.startup.Catalina#load分析:

public void load() {

    ......
    
    //初始化临时目录
    initDirs();

    // Before digester - it may be needed
    //设置额外的系统属性
    initNaming();

    // Create and execute our Digester
    //Digester是apache commons中的一种xml解析器,处理conf/server.xml
    //在这个方法里,读取serverl.xml时通过反射实例化了standardServer对象
    Digester digester = createStartDigester();

    ......

        try {
            inputSource.setByteStream(inputStream);
            digester.push(this);
            //传入流到digester解析xml拼成对象
            digester.parse(inputSource);
        } catch (SAXParseException spe) {
            log.warn("Catalina.start using " + getConfigFile() + ": " +
                    spe.getMessage());
            return;
        } catch (Exception e) {
            log.warn("Catalina.start using " + getConfigFile() + ": " , e);
            return;
        }
        
    ......

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

    // Stream redirection
    //自定义了System.out.PrintStream,写了一个子类SystemLogHandler继承PrintStream,便于多线程下的日志处理
    initStreams();

    // Start the new server
    try {
        //初始化Engine,Executor(用来在connector中管理线程池),Connector,mapperListener(用来监听container的变化的)
        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("Catalina.start", e);
        }
    }

    long t2 = System.nanoTime();
    if(log.isInfoEnabled()) {
        log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
    }
}

类org.apache.catalina.startup.Catalina#start分析:

public void start() {

    ......

    // Start the new server
    try {
        //启动Engine,Executor,Connector,mapperListener
        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;
    }

    ......

    //
    if (await) {
        //调用StandardServer的await方法
        //创建socket连接的服务端对象ServerSocket;
        //循环等待接收客户端发出的命令,如果接收到的命令与SHUTDOWN匹配(由于使用了equals,所以shutdown命令必须是大写的),那么退出循环等待
        
        //执行shutdown.bat的时候,最终使用java命令执行了org.apache.catalina.startup.Bootstrap类中的main方法,参数是stop,
        //通过调用Bootstrap的stopServer方法停止Tomcat,其实质是用反射调用catalinaDaemon(类型是Catalina)的stopServer方法。
        //catalina通过创建Digester解析server.xml文件(此处只解析<Server>标签),以构造出Server容器(此时Server容器的子容器没有被实例化);
        //从实例化的Server容器获取Server的socket监听端口和地址,然后创建Socket对象连接启动Tomcat时创建的ServerSocket,最后向ServerSocket发送SHUTDOWN命令。
        //ServerSocket循环等待接收到SHUTDOWN命令后,最终调用stop方法停止Tomcat。
        await();
        stop();
    }
}

 

tomcat源码 分析 Catalina

原文:https://www.cnblogs.com/grasp/p/10074239.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!