zoukankan      html  css  js  c++  java
  • Tomcat学习小记(二)

    1、Tomcat源码入口

     生命周期统一管理接口:LifeCycle

     实现LifeCycle接口的类:(idea快捷键:Ctrl+h)

    多个组件共同实现LifeCycle接口

     Tomcat启动入口分析:

    (1)根据不同的操作系统,找到启动脚本,startup.bat/startup.sh,我用的是windows操作系统,用的是startup.bat

    startup.bat脚本最后执行函数,执行一个EXECUTABLE变量代表的函数(通过startup.bat去调用catalina.bat脚本),并向函数中传入start参数

     

     (2)catalina.bat脚本中搜索传入的参数"start"

    可以看到要去执行dostart函数,最后找到tomcat是由org.apache.catalina.startup.Bootstrap.main()启动的

     

    CATALINA_BASE:         D:Tomcatapache-tomcat-8.5.9
     CATALINA_HOME:         D:Tomcatapache-tomcat-8.5.9
     Command line argument: -Djava.util.logging.config.file=D:Tomcatapache-tomcat-8.5.9conflogging.properties
     Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
     Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
     Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
     Command line argument: -Dcatalina.base=D:Tomcatapache-tomcat-8.5.9
     Command line argument: -Dcatalina.home=D:Tomcatapache-tomcat-8.5.9
     Command line argument: -Djava.io.tmpdir=D:Tomcatapache-tomcat-8.5.9	emp

    (3)启动类BootStrap,加载初始化以及启动

     public static void main(String args[]) {
    
            synchronized (daemonLock) {
                if (daemon == null) {
                    // Don't set daemon until init() has completed
                    Bootstrap bootstrap = new Bootstrap();
                    try {
                        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);
                    daemon.load(args);//加载初始化,一级一级初始化(对象的实例),connector组件endpoint(socket通信端口bind,尚未accept)
                    daemon.start();//启动,一级一级启动(开始accept接收请求)
                    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);
            }
        }

    2、Tomcat初始化

    daemon.load(args);//加载初始化,一级一级初始化(对象的实例),connector组件endpoint(socket通信端口bind,尚未accept)
    通过load方法通过反射调用catalina.load()方法
    catalina.load()方法中调用digester.parse(inputSource)去解析server.xml文件
    通过得到的server对象调用init()方法去初始化
    init()方法实现LifecycleBase接口的init()方法,LifecycleBase接口的init()方法去调用LifecycleBase.initInternal()方法,而LifecycleBase.initInternal()方法是一个抽象方法,所以具体实现都是在子类中
    //使用了模板方法设计模式,在父类中规定执行的步骤,而其中的某些步骤的实现都是在子类中实现
    @Override public final synchronized void init() throws LifecycleException { if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } try { setStateInternal(LifecycleState.INITIALIZING, null, false);
          //init关键之处,实现子类是standardServer类中 initInternal(); setStateInternal(LifecycleState.INITIALIZED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.initFail", toString()); } }

    standardServer.initInternal()子类中递归调用StandardService.init()方法,对servlet容器和连接器组件进行初始化,后续组件一级一级循环调用,一级一级进行初始化,逻辑相同

     for (int i = 0; i < services.length; i++) {
                services[i].init();
            }

    3、Tomcat启动

    启动流程和初始化相似

    4、Servlet请求分析

    servlet请求——>找到处理servlet实例——>servlet.service()

    connect组件接收servlet请求,并传递到servlet容器中——>Engine引擎根据url找到处理servlet的实例

    5、Servlet请求处理步骤

    请求入口类:NioEndpoint类

    NioEndpoint.Poller(),检查是否有可以被处理的socket请求

    NioEndpoint.startAcceptorThreads(),用来接收请求的线程

  • 相关阅读:
    WAP协议研究笔记—彩信的传输
    应用程序重起自身等几则技巧
    谁妨碍了我们快乐
    国庆长假总结
    关于输入法的两个问题
    反刍
    为什么,一个思维方式的问题,一个习惯的问题,已经意识到了这一点,
    电影池子,
    幻想下,
    意识流,
  • 原文地址:https://www.cnblogs.com/carblack/p/12864679.html
Copyright © 2011-2022 走看看