2.Tomcat分析-顶层结构及启动过程(一)

顶层结构

      Tomcat中最顶层的容器叫Server,代表整个服务器。Server中包含至少一个Service,每个Service用于提供具体的服务;Service主要包含两个部分:Connector和Container;

      Connector用于处理与连接相关的事情,并提供Socket与request,response的转换;Container用于封装和管理Servlet,并具体处理request请求。

      一个Tomcat中只有一个Server,一个Server可以包含多个Service。一个Service只有一个Container,但可以有多个Connector(因为一个Service可以有多个连接,如同时提供http和https连接,也可以提供相同协议不同端口的连接)。



      Tomcat中的Server是由org.apache.catalina.startup.Catalina管理,Catalina是整个Tomcat的管理类,它有三个方法load,start和stop分别用来管理整个服务器的生命周期;

       Catalina的load方法用于根据conf/server.xml文件创建Server并调用Server的init方法进行初始化;start方法用于启动服务器,stop方法用于停止服务器;

       Catalina的start和stop方法在内部分别调用Server的start和stop方法;load方法内部调用了Server的init方法;

       这三个方法都会根据容器的结构逐层调用相应的方法,比如,Server的start方法会调用所有Service的start方法,Service的start方法会调用所包含的Conector和Container的start方法,这样整个服务器就启动了。其他方法也一样,这就是Tomcat的生命周期管理方法

       Catalina还有个方法await,它直接调用了Server的await方法;这个方法的作用是进入一个循环,让主线程不会退出。await也是会逐层调用的。

       Tomcat的入口main方法在org.apache.catalina.startup.Bootstrap中,Bootstrap类似一个CatalinaAdaptor,具体处理过程还是由Catalina来完成。这样做的好处是,可以将启动的入口和具体的管理类分开,从而可以很方便地创建出多种启动方式,每种启动方式只需要写一个相应的CatalinaAdaptor即可;

Bootstrap的启动过程

       如前面所说的,Bootstrap是Tomcat的入口main方法,所以正常情况下,启动Tomcat就是调用Bootstrap的过程。下面就用源码解释其过程。

    public static void main(String args[]) {
        //先新建一个Bootstrap
        if (daemon == null) {
            daemon = new Bootstrap();
            try {
                //初始化ClassLoader,并用ClassLoader创建Catalina实例,赋给catalinaDaemon变量
                daemon.init();
            } catch (Throwable t) {
                handleThrowable(t);
                t.printStackTrace();
                return;
            }
        }else{
            Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
        }
        //处理main传入的参数
        try {
            String command = "start";             //如果args为空,则默认执行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);
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stop")) {
                daemon.stopServer(args);
            } else {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } catch (Throwable t) {
            handleThrowable(t);
            t.printStackTrace();
            System.exit(1);
        }
    }

       这里的main方法非常简单,首先新建Bootstrap,并执行init方法初始化;然后处理main方法传入的命令,如果args参数为空,默认执行start;

       在init方法里初始化ClassLoader,并用ClassLoader创建了Catalina实例,然后赋给catalinaDaemon变量,后面对命令的操作都要使用catalinaDaemon来具体执行;

       对于command.equals("start")的情况,执行顺序为:daemon.setAwait(true),daemon.load(args)和daemon.start()。

       后面的三个方法都通过了反射的方式,调用Catalina的相应方法来进行具体的执行。

    //以start()举例子,另外两个方法是类似的
    public void start(){
        if(catalinaDaemon == null){
            //首先判断catalinaDaemon是否已经初始化,没有的话调用init()进行初始化
            init();
        }
        //利用反射,调用Catalina的start方法
        //下面的调用相当于,((Catalina)catalinaDaemon).start()
        Method method = catalinaDaemon.getClass().getMethod("start",(Class[]) null); 
        method.invoke(catalinaDaemon,(Object[]) null);               //执行start方法
    }

Catalina的启动过程

       setAwait(boolean)用于设置Server启动完成后是否进入等待状态,如果为true则进入;load()方法用于加载配置文件,创建并初始化Server;start()方法用于启动Server;

//org.apache.catalina.startup.Catalina
public void setAwait(boolean b){
    //await属性会在start方法中的服务器启动完成之后使用它来判断是否进入等待状态
    await = b;  
}

        load方法根据conf/server.xml创建Server对象,并赋值给server属性,然后调用server.init方法;

public void load(){
    long t1 = System.nanoTime();
    //创建server
    ......
    try{
       getServer().init();
    }catch(LifecycleException e){
       .....
    }
    .....
}

         Catalina的start方法主要调用了server的start方法启动服务器,并根据await属性判断是否让程序进入等待状态;

public void start() {
     //判断Server是否已经存在
     if(getServer() == null){
         load();
     }
     .....
     try(
        //调用Server的start方法启动服务器
        getServer().start();
     )
     .....
     if(await){
        //进入等待状态
        await(); //直接调用了Server的await方法,它会在内部执行一个while循环
        stop();  //当从awit方法的while循环退出时,就执行stop方法关闭服务器
     }
}

Server的启动过程

        Server接口提供了addService和removeService来添加和删除Service,Server的init和start方法分别循环调用每个Service的init和start方法;

         Server的默认实现是org.apache.catalina.core.StandardServer;

Service的启动过程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值