Tomcat源码解析2-源码结构以及服务启动


最近想着再重新回顾下Tomcat,记得刚学java那时候就是从tomcat搭建启动服务开始的。

找了一下感觉SoyWang总结的Tomcat特别适合大家的借鉴学习,这里就把其中一些未讲解到的地方稍微记录一下,有助于更加熟悉原理:

本机环境:

Tomcat8.5.77

apache-ant1.10.12

1、源码目录结构

bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结尾的(linux命令),另一类是以.bat结尾的(windows命令)

conf目录主要是用来存放tomcat的一些配置文件

server.xml可以设置端口号、设置域名或IP、默认加载的项目、请求编码

web.xml可以设置tomcat支持的文件类型

context.xml可以用来配置数据源之类的

tomcat-users.xml用来配置管理tomcat的用户与权限

logs目录用来存放tomcat在运行过程中产生的日志文件,非常重要的是在控制台输出的日志。(清空不会对tomcat运行带来影响)

在windows环境中,控制台的输出日志在catalina.xxxx-xx-xx.log文件中

在linux环境中,控制台的输出日志在catalina.out文件中

webapps目录用来存放应用程序,当tomcat启动时会去加载webapps目录下的应用程序。可以以文件夹、war包、jar包的形式发布应用。 当然,你也可以把应用程序放置在磁盘的任意位置,在配置文件中映射好就行

该目录是用来存放web项目的,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的项目。其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。http://localhost:8080/examples,进入示例项目。其中examples就是项目名,即文件夹的名字。
在IDEA中启动运行Tomcat,IDEA都会自动生成一个新Tomcat目录文件,可以在Tomcat启动过程中找到路径

LICENSE:许可证

NOTICE:说明文件

2、Tomcat启动参数解析

Tomcat启动的目录为一个main方法类:org.apache.catalina.startup.Bootstrap

添加VM options 启动参数配置

-Dcatalina.home=catalina-home   catalina.home(安装目录)

-Dcatalina.base=catalina-home    catalina.base(工作目录)

Bootstrap启动的时候使用了两个系统变量catalina.home和catalina.base,从官网和源码中的注释可以知道这两者的区别主要是:catalina.home是Tomcat产品的安装目录,而catalina.base是tomcat启动过程中需要读取的各种配置及日志的根目录。

实际上是可以利用这两个系统变量,实现在一台机器上运行多个tomcat实例的目的主要就是利用catalina.base,因为它是Tomcat启动过程中读取各自配置的根目录。(37条消息) Tomcat源码分析-catalina.home和catalina.base_毕小宝的博客-CSDN博客

-Djava.endorsed.dirs=catalina-home/endorsed

java提供了endorsed技术:
关于endorsed:可以的简单理解为-Djava.endorsed.dirs指定的目录面放置的jar文件,将有覆盖系统API的功能。可以牵强的理解为,将自己修改后的API打入到 虚拟机指定的启动API中,取而代之。但是能够覆盖的类是有限制的,其中不包括java.lang包中的类。
这有什么用?

比如java的原生api不能满足需求,假设我们需要修改 ArrayList 类,由于我们的代码都是基于ArrayList做的,那么就必需用到 Java endorsed 技术,将我们自己的ArrayList(注意包和类名和java自带的都是一样的)打成一个jar包,放入到-Djava.endorsed.dirs指定的目录中,这样我们在使用java的ArrayList的时候就会调用的我们定制的代码中,是不是很酷!!

根据官方文档描述:如果不想添加-D参数,如果我们希望基于这个JDK下的都统一改变,那么我们可以将我们修改的jar放到:$JAVA_HOME/jre/lib/endorsed这样基于这个JDK的所有的ArrayList都改变了!!

-Djava.io.tmpdir=catalina-home/temp

java.io.tmpdir 是默认的临时文件路径。 可以通过如下方式打印出具体的文件路径 System.out.println(System.getProperty("java.io.tmpdir"));

-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

-Djava.util.logging.config.file=catalina-home/conf/logging.properties 日志记录相关的

3、启动过程觉得还是要有源码协助比较好,并且断点方式启动,这样便于每一行代码的分析梳理,建议启动分析大家参考如下博文看下整个服务启动的流程图:

(37条消息) Tomcat源码分析之启动过程流程图_Mr_Smile2014的博客-CSDN博客_tomcat源码图

其中理解几个概念:

主进程main thread:
程序执行的入口,可以理解为常用的main 函数。
父进程parent thread:
对于子进程而言, 子进程的创造者,可有多个子进程。 任何进程都有父进程,追根溯源是系统启动程序。对于我们一般写的程序,主进程是最初始的父进程。
子进程child thread:
相对父进程而言, 父进程创建的进程, 子进程只能对应一个父进程。如果没有标记为daemon , 则杀死父进程不会对子进程的运行状态有丝毫影响。
守护进程daemon thread:
即daemon thread,是子进程的一种状态,标记子进程与父进程一起结束。
僵尸进程:
本该结束,但仍在后台运行的子进程。因为某些子进程没有设置daemon 属性,如果杀死父进程,其子进程将会变成“僵尸进程”。僵尸进程的父进程将成为init 进程的子进程。