Tomcat源码分析 · 壹

共 2261字,需浏览 5分钟

 ·

2021-10-01 08:53

前言

从今天开始,我们开始分析tomcat的源码,至于原因嘛,第一Tomcat是非常优秀的web服务器,它占据着全球一半以上的市场份额,就连spring boot这样的顶级框架都在用tomcat做底层实现,这足以说明其流行程度。当然,其流行的另一个重要原因是,它是开源的,它是apache基金会下的一个顶级项目,相比做java开发的小伙伴应该没人不知道tomcat吧。

基于以上原因,我们今天来看下Tomcat的源码实现。

昨天在某乎上看到一个大佬分享了Tomcat的源码视频,大佬说关于源码的学习应该从以下几点入手:

  • 组件及功能
  • 设计模式
  • 线程安全
  • 对比联想

所以本次源码分析我们就从以上几点开始入手。我昨天说要加强设计模式就是从这里看来的,毕竟看清楚了设计模式,源码分析起来就没那么难了。

Tomcat

首先,我们看Tomcat源码的结构:

这个结构和我们平时下载到的发布版本基本上一致。这里源码剖析和版本无关,但是如果线上环境使用的话,建议使用最新版,因为9.0.31以下的版本存在漏洞,关于漏洞加固我们昨天已经分享过了,还没看的小伙伴可以爬个楼看下。

我们先来看下bin下面的启动脚本,从startup脚本中我们可以找到项目启动入口,这里我们以windows环境下的bat脚本为例:

可以看到startup脚本调用的是catalina脚本,而且传递的参数是start

首先从下面的脚本中我们可以推测出,这里最终应该会通过执行Bootstrapmain方法来启动Tomcat,而且由于%1处的参数是start,所以最终他会去调用noJpda语句块:

noJpda语句块中,由于我们的参数是start,所以他会调用doStart语句块:

ddStart操作中,设置了启动参数,最后调用execCme操作:

execCmd语句块中最终通过java命令行的方式,来运行MAINCLASSmain方法启动tomcat:

下面我们就来简单看下Bootstrapmain方法执行过程::

首先,它以单例模式创建了Bootstrap实例,并执行它的初始化操作,最后将创建的对象赋值给daemon对象,如果发生异常会调用handleThrowable方法进行异常处理。这里创建方式是单例模式,首先daemon是一个静态私有变量,同时它被volatile关键字修饰,确保它在修改后对所有线程可见,为了进一步保证线程安全,这里还引入了daemonLock变量,并加了synchronized锁,下面是这两对象的定义及修饰:

main方法的下半部分中,它需要执行daemonload方法和start方法来启动容器,这里发生异常,同样会调用handleThrowable方法来处理异常。另外从这几行代码中,我们可以看出来,command其实只支持通过args参数传入的,需要注意的是,command必须是args的最后一个参数:

下面我们就来逐一看下与 Bootstrap相关的几个方法。

init

首先是init方法,这个方法主要有两部分操作,一部分就是关于类加载器的操作,一部分就是关于Catalina的操作。

initClassLoaders方法中,主要是创建了三个类加载器:

这里的commonservershared分别表示不同的配置名,在creaeteClassLoader方法中会根据该名称从catalina.properties文件中获取对应的配置

在获取配置资源的时候,会从三个地方获取catalina.properties文件,分别是系统的根目录、conf目录、和/org/apache/catalina/startup/包下面,但只会解析其中一个,会按照我们这里说的顺序解析,如果中间任意一个文件不为空,则后面的文件就不会被解析到:

config目录下的catalina.properties文件中,只有common.loader是有值的,其他两个都是空的:

可以看到common.loader共配置了四个路径,分别包括两个目录及其下的jar文件。

首先会在replace方法中替换其中${catalina.base}这样配置,然后在getPaths方法中最终匹配·其中配置的内容。

这里的gatPaths方法就是为了解析出配置文件中的路径,然后返回:

最后,调用ClassLoaderFactorycreaeteClassLoader方法创建了一个URLClassLoader的实例,入参就是出jar文件之外的路径:

好了,由于时间的关系,我们今天就只说init方法中的一部分,剩下的内容明天继续,另外今天打算搞下tomcat的环境,让tomcat能在idea环境下debug

总结

从目前情况来看,tomcat的源码和spring boot比起来,还是比较简单的,当然这也不排除正是经历了spring boot源码的磨砺,才让我们现在看tomcat的源码如此地轻松。

另外有个好消息说下,由于最近一直忘记提交内容,所以今天我专门搞了一个定时任务提交内容,这样以后每天六点定时任务会自动帮我提交内容,我再也不用担心写好的内容忘记提交了,so easy

好了,各位小伙伴晚安吧,我要继续搞环境了!

- END -


浏览 38
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报