1. 程式人生 > >tomcat源碼 分析 Catalina

tomcat源碼 分析 Catalina

nano rap warn nec event handler common bootstrap row

通過查看分析啟動腳本,發現最終調用的入口是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