您当前的位置:首页 > 电脑百科 > 程序开发 > 开源程序 > 源码

Tomcat源码篇-简单到超乎想象的启动流程

时间:2022-02-28 14:46:24  来源:  作者:波哥带你学Java
Tomcat源码篇-简单到超乎想象的启动流程

 

image.png

Tomcat的启动核心流程

  前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核心组件,比如Server,Service肯定都绕不开生命周期的方法。

Tomcat源码篇-简单到超乎想象的启动流程

 

image.png

1.启动的入口

  你可以通过脚本来启动Tomcat服务(startup.bat),但如果你看过脚本的命令,你会发现最终调用的还是Bootstrap中的main方法,所以我们需要从main方法来开始

Tomcat源码篇-简单到超乎想象的启动流程

 

image.png

  然后我们去看main方法中的代码,我们需要重点关注的方法有三个

  1. bootstrap.init()方法
  2. load()方法
  3. start()方法

  也就是在这三个方法中会完成Tomcat的核心操作。

2.init方法

  我们来看下init方法中的代码,非核心的我们直接去掉

    public void init() throws Exception {
        // 创建相关的类加载器
        initClassLoaders();
        // 省略部分代码...
        // 通过反射创建了 Catalina 类对象
        Class<?> startupClass = catalinaLoader
            .loadClass("org.Apache.catalina.startup.Catalina");
        // 创建了 Catalina 实例
        Object startupInstance = startupClass.getConstructor().newInstance();

        // 省略部分代码...
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("JAVA.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        // 把 sharedLoader 设置为了 commonLoader的父加载器
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

        // Catalina 实例 赋值给了 catalinaDaemon
        catalinaDaemon = startupInstance;
    }
  1. 首先是调用了initClassLoaders()方法,这个方法会完成对应的ClassLoader的创建,这个比较重要,后面专门写一篇文章来介绍。
  2. 通过反射的方式创建了Catalina的类对象,并通过反射创建了Catalina的实例
  3. 设置了类加载器的父子关系
  4. 用过成员变量catalinaDaemon记录了我们创建的Catalina实例

  这个是通过bootstrap.init()方法我们可以获取到的有用的信息。然后我们继续往下面看。

3.load方法

  然后我们来看下load方法做了什么事情,代码如下:

    private void load(String[] arguments) throws Exception {

        // Call the load() method
        String methodName = "load"; // load方法的名称
        Object param[];
        Class<?> paramTypes[];
        if (arguments==null || arguments.length==0) {
            paramTypes = null;
            param = null;
        } else {
            paramTypes = new Class[1];
            paramTypes[0] = arguments.getClass();
            param = new Object[1];
            param[0] = arguments;
        }
        // catalinaDaemon 就是在 init中创建的 Catalina 对象
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled()) {
            log.debug("Calling startup class " + method);
        }
        // 会执行 Catalina的load方法
        method.invoke(catalinaDaemon, param);
    }

  上面的代码非常简单,通过注释我们也可以看出该方法的作用是调用 Catalina的load方法。所以我们还需要加入到Catalina的load方法中来查看,代码同样比较长,只留下关键代码

    public void load() {

        if (loaded) {
            return; // 只能被加载一次
        }
        loaded = true;

        initDirs(); // 废弃的方法

        // Before digester - it may be needed
        initNaming(); // 和JNDI 相关的内容 忽略

        // Create and execute our Digester
        // 创建并且执行我们的 Digester 对象  Server.xml
        Digester digester = createStartDigester();

        // 省略掉了 Digester文件处理的代码

        getServer().setCatalina(this); // Server对象绑定 Catalina对象
        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());

        // Stream redirection
        initStreams();
        // 省略掉了部分代码...
         getServer().init(); // 完成 Server  Service Engine Connector等组件的init操作

    }

把上面的代码简化后我们发现这个Load方法其实也是蛮简单的,就做了两件事。

  1. 通过Apache下的Digester组件完成了Server.xml文件的解析
  2. 通过getServer().init() 方法完成了Server,Service,Engin,Connector等核心组件的初始化操作,这块和前面的LifecycleBase呼应起来了。
Tomcat源码篇-简单到超乎想象的启动流程

 

image.png

  如果生命周期的内容不清楚,请看上一篇文章的介绍。

4.start方法

  最后我们来看下start方法的代码。

    public void start() throws Exception {
        if (catalinaDaemon == null) {
            init(); // 如果 catalinaDaemon 为空 初始化操作
        }
        // 获取的是 Catalina 中的 start方法
        Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
        // 执行 Catalina 的start方法
        method.invoke(catalinaDaemon, (Object [])null);
    }

  上面的代码逻辑也很清楚,就是通过反射的方式调用了Catalina对象的start方法。所以进入Catalina的start方法中查看。

    public void start() {

        if (getServer() == null) {
            load(); // 如果Server 为空 重新 init 相关的组件
        }

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

        // Start the new server  关键方法--->启动Server
        try {
            getServer().start();
        } catch (LifecycleException e) {
            // 省略...
        }

        // 省略...

        // Register shutdown hook  注册关闭的钩子
        if (useShutdownHook) {
            // 省略...
        }

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

  通过上面的代码我们可以发现核心的代码还是getServer.start()方法,也就是通过Server对象来嵌套的调用相关注解的start方法。

Tomcat源码篇-简单到超乎想象的启动流程

 

image.png

5.核心流程的总结

我们可以通过下图来总结下Tomcat启动的核心流程

Tomcat源码篇-简单到超乎想象的启动流程

 

image.png

  从图中我们可以看到Bootstrap其实没有做什么核心的事情,主要还是Catalina来完成的。

  本文只是从Tomcat的启动核心流程来讲解,还有些具体的实现细节没有介绍到,会在后续的文章中给大家细细到来,欢迎关注收藏哦!



Tags:Tomcat   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
image.pngTomcat的启动核心流程&emsp;&emsp;前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核...【详细内容】
2022-02-28  Tags: Tomcat  点击:(0)  评论:(0)  加入收藏
1、一个简单的 HTTP 服务器在Web应用中,浏览器请求一个URL,服务器就把生成的HTML网页发送给浏览器,而浏览器和服务器之间的传输协议是HTTP,那么接下来我们看下如何用Java来实现...【详细内容】
2022-02-25  Tags: Tomcat  点击:(11)  评论:(0)  加入收藏
1、获取SpringBoot内置Tomcat自动配置类:  在SpringBoot项目中引入spring-boot-starter-web依赖,就默认使用Tomcat容器,该依赖中引入 spring-boot-starter-tomcat、spring-we...【详细内容】
2022-02-22  Tags: Tomcat  点击:(17)  评论:(0)  加入收藏
1. 整体架构简析#如果将Tomca它的结构高度抽象的话,那么Tomcat其实可以看成只是有连接器(Connector)和容器(Container)两个组件构成。其中Connector组件负责在服务器端处理客户端...【详细内容】
2021-09-30  Tags: Tomcat  点击:(83)  评论:(0)  加入收藏
开源的 Java Web 应用服务器,实现了 Java EE(Java Platform Enterprise Edition)的部 分技术规范,比如 Java Servlet、Java Server Page、JSTL、Java WebSocket。Java EE 是 S...【详细内容】
2021-09-17  Tags: Tomcat  点击:(84)  评论:(0)  加入收藏
一、前言server.xml 配置,是 Tomcat启动配置,从配置结构可以看出 Tomcat 的整体架构。如果能够了解其常用配置项,对 Tomcat有一个高屋建瓴的把握,然后再庖丁解牛,一步步深入源码...【详细内容】
2021-07-04  Tags: Tomcat  点击:(103)  评论:(0)  加入收藏
一,undertow介绍 1,undertow简介:Undertow是RedHAT红帽公司开源的产品,采用java开发,是一款灵活,高性能的web服务器,提供了NIO的阻塞/非阻塞API,也是Wildfly的默认Web容器。在javaw...【详细内容】
2021-05-07  Tags: Tomcat  点击:(198)  评论:(0)  加入收藏
说明最近项目上遇到一些https的问题,需要在tomcat里面测试一下如何开启https协议访问网站,在网上查了一些资料,自己也试了很多次,终于成功搞定了,下面跟大家分享一下我的一点经验...【详细内容】
2021-04-20  Tags: Tomcat  点击:(181)  评论:(0)  加入收藏
1 Jetty与glassfish的基本介绍1.1 研究背景及意义下图是对几个主流的应用服务器使用比率的粗率统计结果做出的一个饼图。这个图的数据也许不够精确,但它还是可以在一定程度上...【详细内容】
2021-04-06  Tags: Tomcat  点击:(213)  评论:(0)  加入收藏
Tomcat是什么?Tomcat是web容器。你在做web项目时,多数需要http协议,也就是基于请求和响应,比如你在百度输入一行内容搜索,那么百度服务器如何处理这个请求呢,他需要创建servlet来...【详细内容】
2021-03-24  Tags: Tomcat  点击:(300)  评论:(0)  加入收藏
▌简易百科推荐
image.pngTomcat的启动核心流程&emsp;&emsp;前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核...【详细内容】
2022-02-28  波哥带你学Java    Tags:Tomcat   点击:(0)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的 Easy-Es是一款简化ElasticSearch搜索引擎操作的开源框...【详细内容】
2022-02-28  GitHub精选    Tags:Easy-Es   点击:(2)  评论:(0)  加入收藏
# pip install pyechartsfrom pyecharts import options as optsfrom pyecharts.charts import Map# 实例化地图对象china_map = Map()# 各省份的数据data = [ [&#39;广...【详细内容】
2022-02-24  帅帅的Python    Tags:pyecharts   点击:(12)  评论:(0)  加入收藏
HTML网站右键禁用F12代码 屏蔽审查元素 防止修改页面代码<script>//禁止右键 function click(e) { if (document.all) { if (event.button==2||event.button==3) { alert("...【详细内容】
2022-02-22      Tags:禁用F12   点击:(15)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的是一个简单又灵活的 flutter canvas 图形动画库Zerker...【详细内容】
2022-02-11  GitHub精选    Tags:Zerker   点击:(17)  评论:(0)  加入收藏
1、服务器系统配置初始化#/bin/bash# 安装系统性能分析工具及其他yum install gcc make autoconf vim sysstat net-tools iostat iftop iotp wget lrzsz lsof unzip openssh...【详细内容】
2022-02-08  呆萌小可萘日常    Tags:shell 脚本   点击:(21)  评论:(0)  加入收藏
奇虎360 1.MySQL中间层 AtlasAtlas是由 Qihoo 360, Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础...【详细内容】
2022-02-07  linux上的码农    Tags:开源项目   点击:(25)  评论:(0)  加入收藏
定时任务,是在日常开发需求中总会遇到的,我们往往会有一些简单的脚本工作,希望能够每小时或每天执行一次。当这类需求变得多起来后,这些零散的任务脚本就会变得难以管理,尤其是它...【详细内容】
2022-02-07  每日开源代码    Tags:QingLong   点击:(70)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条