[Tomcat6.0源码]组件的启动

1.Bootstrap初始化后,执行start(),调用Catalina.start():

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

        if (getServer() == null) {
            load();
        }

        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }

        long t1 = System.nanoTime();
        
        // Start the new server
        if (getServer() instanceof Lifecycle) {
            try {
                ((Lifecycle) getServer()).start();
            } catch (LifecycleException e) {
                log.error("Catalina.start: ", e);
            }
        }

        long t2 = System.nanoTime();
        if(log.isInfoEnabled())
            log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");

        try {
            // Register shutdown hook
            if (useShutdownHook) {
                if (shutdownHook == null) {
                    shutdownHook = new CatalinaShutdownHook();
                }
                Runtime.getRuntime().addShutdownHook(shutdownHook);
                
                // If JULI is being used, disable JULI's shutdown hook since
                // shutdown hooks run in parallel and log messages may be lost
                // if JULI's hook completes before the CatalinaShutdownHook()
                LogManager logManager = LogManager.getLogManager();
                if (logManager instanceof ClassLoaderLogManager) {
                    ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                            false);
                }
            }
        } catch (Throwable t) {
            // This will fail on JDK 1.2. Ignoring, as Tomcat can run
            // fine without the shutdown hook.
        }

        if (await) {
            await();
            stop();
        }

    }

2.((Lifecycle) getServer()).start();调用StandardServer.start();

    /**
     * Prepare for the beginning of active use of the public methods of this
     * component.  This method should be called before any of the public
     * methods of this component are utilized.  It should also send a
     * LifecycleEvent of type START_EVENT to any registered listeners.
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    public void start() throws LifecycleException {

        // Validate and update our current component state
        if (started) {
            log.debug(sm.getString("standardServer.start.started"));
            return;
        }

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Start our defined Services
        synchronized (services) {
            for (int i = 0; i < services.length; i++) {
                if (services[i] instanceof Lifecycle)
                    ((Lifecycle) services[i]).start();
            }
        }

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

    }

3.遍历执行((Lifecycle) services[i]).start();调用与其相关的所有StandardService.start();

    public void start() throws LifecycleException {

        // Validate and update our current component state
        if (started) {
            if (log.isInfoEnabled()) {
                log.info(sm.getString("standardService.start.started"));
            }
            return;
        }
        
        if( ! initialized )
            init(); 

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Start our defined Container first
        if (container != null) {
            synchronized (container) {
                if (container instanceof Lifecycle) {
                    ((Lifecycle) container).start();
                }
            }
        }

        synchronized (executors) {
            for ( int i=0; i<executors.size(); i++ ) {
                executors.get(i).start();
            }
        }

        // Start our defined Connectors second
        synchronized (connectors) {
            for (int i = 0; i < connectors.length; i++) {
                try {
                    ((Lifecycle) connectors[i]).start();
                } catch (Exception e) {
                    log.error(sm.getString(
                            "standardService.connector.startFailed",
                            connectors[i]), e);
                }
            }
        }
        
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

    }

4.这里先后启动StandardEngine和Connector。

    1)执行((Lifecycle) container).start();即StandardEngine.start()。 

    public void start() throws LifecycleException {
        if( started ) {
            return;
        }
        if( !initialized ) {
            init();
        }

        // Look for a realm - that may have been configured earlier. 
        // If the realm is added after context - it'll set itself.
        if( realm == null ) {
            ObjectName realmName=null;
            try {
                realmName=new ObjectName( domain + ":type=Realm");
                if( mserver.isRegistered(realmName ) ) {
                    mserver.invoke(realmName, "init", 
                            new Object[] {},
                            new String[] {}
                    );            
                }
            } catch( Throwable t ) {
                log.debug("No realm for this engine " + realmName);
            }
        }
            
        // Log our server identification information
        //System.out.println(ServerInfo.getServerInfo());
        if(log.isInfoEnabled())
            log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
        if( mbeans != null ) {
            try {
                Registry.getRegistry(null, null)
                    .invoke(mbeans, "start", false);
            } catch (Exception e) {
                log.error("Error in start() for " + mbeansFile, e);
            }
        }

        // Standard container startup
        super.start();

    }

StandardEngine在《组件的初始化》中未参与初始化,所以会执行StandardEngine.init(),不过这个init也没干什么事。

最后一行super.start()调用的是ContainerBase.start():

    public synchronized void start() throws LifecycleException {

        // Validate and update our current component state
        if (started) {
            if(log.isInfoEnabled())
                log.info(sm.getString("containerBase.alreadyStarted", logName()));
            return;
        }
        
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

        started = true;

        // Start our subordinate components, if any
        if ((loader != null) && (loader instanceof Lifecycle))
            ((Lifecycle) loader).start();
        logger = null;
        getLogger();
        if ((logger != null) && (logger instanceof Lifecycle))
            ((Lifecycle) logger).start();
        if ((manager != null) && (manager instanceof Lifecycle))
            ((Lifecycle) manager).start();
        if ((cluster != null) && (cluster instanceof Lifecycle))
            ((Lifecycle) cluster).start();
        if ((realm != null) && (realm instanceof Lifecycle))
            ((Lifecycle) realm).start();
        if ((resources != null) && (resources instanceof Lifecycle))
            ((Lifecycle) resources).start();

        // Start our child containers, if any
        Container children[] = findChildren();
        for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof Lifecycle)
                ((Lifecycle) children[i]).start();
        }

        // Start the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle)
            ((Lifecycle) pipeline).start();

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(START_EVENT, null);

        // Start our thread
        threadStart();

        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

    }

 StandarHost、StandardContext都会继承这个ContainerBase,且他们的启动最终也是交给这个ContainerBase来处理。所以,有必要了解下这个ContainerBase,start方法里边出镜率最高的应该是lifecycle:

protected LifecycleSupport lifecycle = new LifecycleSupport(this);

它是直接在ContainerBase的属性中new出来的,参数是基类对象,StandardEngine实例化的时候,这个this就是StandardEngine对象。(这个应该也是一种设计模式?)LifecycleSupport有三个重要的方法addLifecycleListener()、fireLifecycleEvent()、removeLifecycleListener()。addLifecycleListener在初始化的时候经常用到,它把所有相关的监听器都加到LifecycleSupport的listeners数组中。

上面代码lifecycle出现的时候都是执行fireLifecycleEvent():

    /**
     * Notify all lifecycle event listeners that a particular event has
     * occurred for this Container.  The default implementation performs
     * this notification synchronously using the calling thread.
     *
     * @param type Event type
     * @param data Event data
     */
    public void fireLifecycleEvent(String type, Object data) {

        if (Lifecycle.INIT_EVENT.equals(type)) {
            state = "INITIALIZED";
        } else if (Lifecycle.BEFORE_START_EVENT.equals(type)) {
            state = "STARTING_PREP";
        } else if (Lifecycle.START_EVENT.equals(type)) {
            state = "STARTING";
        } else if (Lifecycle.AFTER_START_EVENT.equals(type)) {
            state = "STARTED";
        } else if (Lifecycle.BEFORE_STOP_EVENT.equals(type)) {
            state = "STOPPING_PREP";
        } else if (Lifecycle.STOP_EVENT.equals(type)) {
            state = "STOPPING";
        } else if (Lifecycle.AFTER_STOP_EVENT.equals(type)) {
            state = "STOPPED";
        } else if (Lifecycle.DESTROY_EVENT.equals(type)) {
            state = "DESTROYED";
        }
        LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
        LifecycleListener interested[] = listeners;
        for (int i = 0; i < interested.length; i++)
            interested[i].lifecycleEvent(event);

    }

经过LifecycleEvent的封装后(这又是一个设计模式?)将会调用各个LifecycleListener.lifecycleEvent()。回过头来看看StandardEngine绑了几个LifecycleListener,具体有多少要看看配置文件,但至少有这个EngineConfig (见《Engine的实例化》)。EngineConfig.lifecycleEvent():

    public void lifecycleEvent(LifecycleEvent event) {

        // Identify the engine we are associated with
        try {
            engine = (Engine) event.getLifecycle();
        } catch (ClassCastException e) {
            log.error(sm.getString("engineConfig.cce", event.getLifecycle()), e);
            return;
        }

        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.START_EVENT))
            start();
        else if (event.getType().equals(Lifecycle.STOP_EVENT))
            stop();

    }

经过这样传递,StandardEngine继承的ContainerBase.start()中,lifecycle.fireLifecycleEvent(START_EVENT, null);最终会执行EngineConfig.start():

    protected void start() {

        if (engine.getLogger().isDebugEnabled())
            engine.getLogger().debug(sm.getString("engineConfig.start"));

    }

尼玛。。。绕这么多就为了记个日志。不过这一步会在((Lifecycle) children[i]).start()之后执行。

         (1)((Lifecycle) children[i]).start();调用StandardHost.start():

    public synchronized void start() throws LifecycleException {
        if( started ) {
            return;
        }
        if( ! initialized )
            init();

        // Look for a realm - that may have been configured earlier. 
        // If the realm is added after context - it'll set itself.
        if( realm == null ) {
            ObjectName realmName=null;
            try {
                realmName=new ObjectName( domain + ":type=Realm,host=" + getName());
                if( mserver.isRegistered(realmName ) ) {
                    mserver.invoke(realmName, "init", 
                            new Object[] {},
                            new String[] {}
                    );            
                }
            } catch( Throwable t ) {
                log.debug("No realm for this host " + realmName);
            }
        }
            
        // Set error report valve
        if ((errorReportValveClass != null)
            && (!errorReportValveClass.equals(""))) {
            try {
                boolean found = false;
                if(errorReportValveObjectName != null) {
                    ObjectName[] names = 
                        ((StandardPipeline)pipeline).getValveObjectNames();
                    for (int i=0; !found && i<names.length; i++)
                        if(errorReportValveObjectName.equals(names[i]))
                            found = true ;
                    }
                    if(!found) {          	
                        Valve valve = (Valve) Class.forName(errorReportValveClass)
                        .newInstance();
                        addValve(valve);
                        errorReportValveObjectName = ((ValveBase)valve).getObjectName() ;
                    }
            } catch (Throwable t) {
                log.error(sm.getString
                    ("standardHost.invalidErrorReportValveClass", 
                     errorReportValveClass), t);
            }
        }
        if(log.isDebugEnabled()) {
            if (xmlValidation)
                log.debug(sm.getString("standardHost.validationEnabled"));
            else
                log.debug(sm.getString("standardHost.validationDisabled"));
        }
        super.start();

    }

           同样的super.start()会执行ContainerBase.start(),而ContainerBase.start()会执行它children.start()即StandardContext.start()。然后再执行其所有绑定LifecycleListener,其中HostConfig很重要,会负责部署所有项目,HostConfig.start():

    /**
     * Process a "start" event for this Host.
     */
    public void start() {

        if (log.isDebugEnabled())
            log.debug(sm.getString("hostConfig.start"));

        try {
            ObjectName hostON = new ObjectName(host.getObjectName());
            oname = new ObjectName
                (hostON.getDomain() + ":type=Deployer,host=" + host.getName());
            Registry.getRegistry(null, null).registerComponent
                (this, oname, this.getClass().getName());
        } catch (Exception e) {
            log.error(sm.getString("hostConfig.jmx.register", oname), e);
        }

        if (host.getDeployOnStartup())
            deployApps();
        
    }

StandardContext.start()也是先把children.start(),再执行ContextConfig.start(),conf/server.xml并没有配置相关的Context所以不会去执行children.start()。

但是会在HostConfig中部署项目的时候去将项目Context加到host的children中。

ContextConfig会调用WebRuleSet.addRuleInstances():解析web.xml。

这些ContainerBase类的设计:

不断的先调用children.start(),在调用自身的listener的设计有点像递归。(肯定是一种设计模式!)


2)执行((Lifecycle) connectors[i]).start();即Connector.start()。

    public void start() throws LifecycleException {
        if( !initialized )
            initialize();

        // Validate and update our current state
        if (started ) {
            if(log.isInfoEnabled())
                log.info(sm.getString("coyoteConnector.alreadyStarted"));
            return;
        }
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // We can't register earlier - the JMX registration of this happens
        // in Server.start callback
        if ( this.oname != null ) {
            // We are registred - register the adapter as well.
            try {
                Registry.getRegistry(null, null).registerComponent
                    (protocolHandler, createObjectName(this.domain,"ProtocolHandler"), null);
            } catch (Exception ex) {
                log.error(sm.getString
                          ("coyoteConnector.protocolRegistrationFailed"), ex);
            }
        } else {
            if(log.isInfoEnabled())
                log.info(sm.getString
                     ("coyoteConnector.cannotRegisterProtocol"));
        }

        try {
            protocolHandler.start();
        } catch (Exception e) {
            String errPrefix = "";
            if(this.service != null) {
                errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
            }

            throw new LifecycleException
                (errPrefix + " " + sm.getString
                 ("coyoteConnector.protocolHandlerStartFailed", e));
        }

        if( this.domain != null ) {
            mapperListener.setDomain( domain );
            //mapperListener.setEngine( service.getContainer().getName() );
            mapperListener.init();
            try {
                ObjectName mapperOname = createObjectName(this.domain,"Mapper");
                if (log.isDebugEnabled())
                    log.debug(sm.getString(
                            "coyoteConnector.MapperRegistration", mapperOname));
                Registry.getRegistry(null, null).registerComponent
                    (mapper, mapperOname, "Mapper");
            } catch (Exception ex) {
                log.error(sm.getString
                        ("coyoteConnector.protocolRegistrationFailed"), ex);
            }
        }
    }

protocolHandler.start();从《Connector的实例化》中可知,8080端口对应的protocolHandler为Http11Protocol对象。Http11Protocol.start():

    public void start() throws Exception {
        if (this.domain != null) {
            try {
                tpOname = new ObjectName
                    (domain + ":" + "type=ThreadPool,name=" + getName());
                Registry.getRegistry(null, null)
                    .registerComponent(endpoint, tpOname, null );
            } catch (Exception e) {
                log.error("Can't register endpoint");
            }
            rgOname=new ObjectName
                (domain + ":type=GlobalRequestProcessor,name=" + getName());
            Registry.getRegistry(null, null).registerComponent
                ( cHandler.global, rgOname, null );
        }

        try {            

endpoint.start(); } catch (Exception ex) { log.error(sm.getString("http11protocol.endpoint.starterror"), ex); throw ex; } if (log.isInfoEnabled()) log.info(sm.getString("http11protocol.start", getName())); }

endpoint.start();调用的是JIoEndpoint.start():

    public void start()
        throws Exception {
        // Initialize socket if not done before
        if (!initialized) {
            init();
        }
        if (!running) {
            running = true;
            paused = false;

            // Create worker collection
            if (executor == null) {
                workers = new WorkerStack(maxThreads);
            }

            // Start acceptor threads
            for (int i = 0; i < acceptorThreadCount; i++) {
                Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
                acceptorThread.setPriority(threadPriority);
                acceptorThread.setDaemon(daemon);
                acceptorThread.start();
            }
        }
    }

acceptorThread.start();调用的是Acceptor.run():

    /**
     * Server socket acceptor thread.
     */
    protected class Acceptor implements Runnable {


        /**
         * The background thread that listens for incoming TCP/IP connections and
         * hands them off to an appropriate processor.
         */
        public void run() {

            // Loop until we receive a shutdown command
            while (running) {

                // Loop if endpoint is paused
                while (paused) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }

                // Accept the next incoming connection from the server socket
                try {
                    Socket socket = serverSocketFactory.acceptSocket(serverSocket);
                    serverSocketFactory.initSocket(socket);
                    // Hand this socket off to an appropriate processor
                    if (!processSocket(socket)) {
                        // Close socket right away
                        try {
                            socket.close();
                        } catch (IOException e) {
                            // Ignore
                        }
                    }
                }catch ( IOException x ) {
                    if ( running ) log.error(sm.getString("endpoint.accept.fail"), x);
                } catch (Throwable t) {
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }

                // The processor will recycle itself when it finishes

            }

        }

    }

线程被阻塞,监听端口上的请求。各组件start完成,tomcat已启动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 要下载Tomcat 6.0,可以按照以下步骤进行操作: 1. 打开一个互联网浏览器(比如Chrome、Firefox)。 2. 在浏览器的搜索栏中输入“Tomcat 6.0下载”并按下回车键。 3. 在搜索结果中,找到Apache Tomcat官方网站的链接并点击进入。 4. 在官方网站的主页上,找到“Download”(下载)选项,并点击进入下载页面。 5. 在下载页面上,会列出不同版本的Tomcat,找到Tomcat 6.0版本并点击下载链接。 6. 选择合适的下载选项,根据操作系统选择适当的压缩包(.zip或.tar.gz)。 7. 确定下载存储路径,点击下载按钮开始下载。 8. 下载完成后,找到存储路径位置,解压下载的压缩包。 9. 在解压后的文件夹中,找到bin目录,里面包含了启动Tomcat所需的执行文件。 10. 配置Tomcat环境变量(如果需要)。 11. 最后,可以通过运行启动文件(例如startup.bat或catalina.sh)启动Tomcat服务器。 通过这些步骤,您就可以成功下载并开始使用Tomcat 6.0。请注意,因版本更新频繁,建议使用最新版本的Tomcat来获得更好的性能和安全性。 ### 回答2: Tomcat 6.0是Apache基金会开发的一款Java Servlet和JavaServer Pages(JSP)的开Web服务器。要下载Tomcat 6.0,可以按照以下步骤进行: 1. 打开Apache Tomcat的官方网站(https://tomcat.apache.org/)。 2. 在网站上找到Tomcat 6.0版本的下载页面。 3. 点击下载链接,选择合适的安装包。通常会有Windows平台和Unix/Linux平台的不同版本可供选择。 4. 选择一个合适的镜像站点来下载安装包,以确保下载速度快且稳定。 5. 下载完成后,找到下载的安装包文件,通常是一个压缩包文件(如.tar、.zip等),并将其解压到你想要安装的目录中。 6. 在安装目录中找到Tomcat启动脚本(如startup.bat或catalina.sh)并运行它,以启动Tomcat服务器。 7. 打开一个Web浏览器,输入http://localhost:8080(默认端口号)来访问Tomcat服务器的默认欢迎页面,以确保Tomcat已经正确安装和启动Tomcat 6.0是一个相对较老的版本,如果你需要使用更新的功能或修复更多的bug,可以考虑升级到更高版本的Tomcat,如Tomcat 7.0、8.0或9.0等。升级过程与上述下载过程类似。记得在安装新版本之前备份现有的配置和应用程序文件,以免丢失重要数据。 ### 回答3: 要下载Tomcat 6.0,您可以按照以下步骤进行: 1. 打开您喜欢使用的网络浏览器,例如Google Chrome,Mozilla Firefox等。 2. 在搜索引擎中输入“Tomcat 6.0下载”,然后按下“Enter”键。 3. 您将看到许多结果,其中一个是Apache Tomcat官方网站。点击该网站链接以继续。 4. 在Apache Tomcat官方网站上,您将找到各种版本的Tomcat。找到并选择Tomcat 6.0版本。 5. 在Tomcat 6.0版本的页面上,您可以找到各种文件和安装程序。根据您的操作系统选择适当的文件。 6. 点击选定的文件链接,然后系统将提示您选择文件下载位置。选择一个方便您访问的位置,然后点击“保存”。 7. 下载过程可能需要一些时间,具体取决于您的网络连接速度。请耐心等待,直到下载完成。 8. 一旦下载完成,转到您选择的下载位置。您将找到一个压缩文件,例如.tar.gz或.zip。 9. 解压缩该文件,并根据官方文档中提供的说明进行安装。 10. 安装完成后,您可以启动Tomcat 6.0并使用它来运行您的Java Web应用程序。 请注意,确保从官方网站下载Tomcat以确保文件的安全性和可靠性。并且,根据您的操作系统选择适当的版本和文件,以免发生兼容性问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值