idea configuration没有tomcat_Tomcat源码调试搭建

儿时读三国,纯属看热闹,只懂英雄豪气。不想更多的,到后来明白了一些道理,读懂却已是中年人。天下大势,分久必合,合久必分。向往曹操:挥师百万,号令天下。佩服司马懿:一路隐忍,最后给予致命一击,重拾人生巅峰。刘备那身在局中,却始终能看清局势的本事。吕布被称为三姓家奴,投靠人更多的刘备为何没有冠以如此称呼?因为他不曾背叛过自己投靠的势力。

相信大家都听过水镜先生司马徽预言的这句话,卧龙凤雏,得一人可以得天下,这个“卧龙”便是诸葛亮,这个“凤雏”则是庞统。刘备卧龙和凤雏都得到了,为什么最后还是得不到天下呢?其实,这句话的后面还有一句,子初孝直,若亡一人则汉室难兴。

我们在上一节中已经介绍了Tomcat功能及架构分析,本篇主要是对其源码的调试及其分析纪要:

源码调试搭建

首先需要下载tomcat的源码及其构建包,可以在其官网自行下载,如下我用的8.5.58版本的:

f7b2c6c663302cb9e96c3fc740508ab6.png

然后分别解压,看下src目录结构:

7d58a55387005b4de4150ea3c93916e0.png

接下来我们会使用maven来构建工程,所以需要在src根目录下新建一个pom文件,添加如下内容:

xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0modelVersion><groupId>com.yilimaizigroupId><artifactId>tomcat8artifactId><version>8.5version><name>tomcat源码调试name><properties><configuration.version>1.9configuration.version><maven.compiler.target>1.8maven.compiler.target><maven.compiler.source>1.8maven.compiler.source><java.version>1.8java.version><project.build.sourceEncoding>UTF-8project.build.sourceEncoding>properties><dependencies><dependency><groupId>javax.xmlgroupId><artifactId>jaxrpcartifactId><version>1.1version>dependency><dependency><groupId>javax.xml.soapgroupId><artifactId>javax.xml.soap-apiartifactId><version>1.4.0version>dependency><dependency><groupId>wsdl4jgroupId><artifactId>wsdl4jartifactId><version>1.6.2version>dependency><dependency><groupId>org.eclipse.jdt.core.compilergroupId><artifactId>ecjartifactId><version>4.5.1version>dependency><dependency><groupId>antgroupId><artifactId>antartifactId><version>1.7.0version>dependency><dependency><groupId>org.easymockgroupId><artifactId>easymockartifactId><version>3.4version>dependency>dependencies><build><finalName>tomcat8.5finalName><sourceDirectory>javasourceDirectory><resources><resource><directory>javadirectory>resource>resources><plugins><plugin><groupId>org.apache.maven.pluginsgroupId><artifactId>maven-compiler-pluginartifactId><version>3.1version><configuration><encoding>utf-8encoding>configuration>plugin>plugins>build>project>

接着在src根目录下新建source目录,把下载的构建包解压后的conf和webapps目录整个copy到其source目录下;

然后在idea中配置其启动类BootStrap的启动参数:

c4348276fd49d24d8c9e8f497325cbbd.png

在VM options 中添加配置:

8ebb54472fc5c2ae7530460ebdcfbd7c.png

相关路径请以实际的环境更改即可。

最后我们便可启动应用程序,启动完后打开浏览器访问8080端口

3ee622f9a19e4ef44f7d05dd7a61f00e.png

会发现报错了,这是因为jsp转servlet的引擎没有初始化导致的,此时需要在

ContextConfig类中的

configureStart

方法里添加如下的代码即可:

context.addServletContainerInitializer(new JasperInitializer(),null);

7b2c9bb3b0acfcdbb2f87ecd18e5bbcb.png

重新启动,再次访问即可,熟悉的页面出现了:

09db54275244cc03beef2a721cffd6f5.png

源码分析-启动

还记得上一节中Tomcat功能及架构分析提到了很多的组件吗?tomcat要启动,肯定要把组件实例化(如实例创建-->实例销毁)。tomcat中那么多组件,为了统一规范他们生命周期,tomcat抽象出了LifeCycle生命周期接口。

我们一起来看下这个接口:

beba568fef845cb53793382e650d9b56.png

果不其然,定义了一系列的生命周期的接口,在右侧看到了我们熟悉的组件都实现了LifeCycle接口。

首先我们来看下构建包bin目录下的startup.sh的内容

c24d95d32fb366f47d1b474ebe13d06e.png

发现最后shell脚本调用的是catalina.sh的脚本并传入了start参数,我们继续跟踪,在catalina的脚本里,最终执行的是:

3b8ae4b2214d587f0b39bd61f433e7ba.png

以上变量参数就不带大家分析了,有兴趣可以自行查看~我们主要看

Bootstrap

那一行内容,及其开头的 $_RUNJAVA变量,其他是辅助参数,在

setclasspath.sh 脚本中我们看到了$_RUNJAVA变量的定义,实际是java命令

44cabe81f1c20807a1bbcac98e2b6cf7.png

所以startup.sh启动命令最终就等效于

java org.apache.catalina.startup.Bootstrap start 

由此我们也知道了在

Bootstrap

类中一定有个main方法:

3890fe1b45da54a85833f9951981054a.png

由此,我们正式进入了启动类的流程分析。

a3d225d2af5adb05ce49a758b1edd4fc.png

初始化类加载器,然后实例化Catalina对象,并赋值给catalinaDaemon

432fbbe5ac4a26803c6a2c037a431e53.png

继续回到主函数:(把bootstrap实例赋值给daemon)

d08951f65baa7bc5665b5319d32a96a6.png

接下来就分两步骤走了,一个是初始化加载过程,一个start启动过程。我们先看下load方法:

23715c960a9a07ede00fda7a8122e7cc.png

发现通过反射调用了catalina的load方法,因内容较多,说下主要做了哪些动作:通过

Digester

来解析server.xml内容

43890d4a8ce4948b27c9f62816bcbfd1.png

然后初始化server

328f7ef4e31d58cfcea8fa9984c85a2b.png

接下来就涉及到之前提到的生命周期的管理了,LifeCycle

其抽象类实现

LifeCycleBase

定义了生命周期的初始化模版方法:

9884306c05544f118e739d5bf8b6971c.png

所有实现Lifecycle接口的组件,初始化先调用Lifecyclebase的init方法,然后在调用各自组件实现的

initInternal

方法,我们看其server的实现

30127ca49c48040c71328ef674d96b1d.png

通过server组件,拿到其子组件service,我们在上一节也分析过,一个server下可以有多个service组件,所以这边用的是循环去初始化。按照我们刚才说的模版方法,会调用lifecyclebase的init方法,然后到standardservice的

initInternal

方法

fc0922f5254fa70f334a650bea0bda3f.png

这边分两个组件各自初始化了,在上节中我们知道service下面有connector和container子组件,所以这边分别对其初始化。我们先看engine的初始化过程,还是会遵循上面的模版方法过程,我们直接到

StandardEngine

21edfbabe7125af8d5a86ea6957bbbdd.png

继续进入super.initInternal方法

45d6095b55a77d97d2d9c17e287cdea4.png

会发现此时并没有初始化容器,只是new了一个线程池,便于在start过程中快速的创建需要的容器。

我们继续回到service里的connector的初始化过程,流程依旧按照模版方法最终进入到connector的

initInternal

87161d07cd8f4ff59d97e9505039d60e.png

首先会把协议处理器会adapter绑定,然后协议处理器初始化,tomcat8默认是http11的协议

b953f94df6c4369c172492747bb0f0a9.png

到其父类中

7183477b3c030f85da70b37a9ee74232.png

来到

50422789b35c1bd2d456e897e4aeefba.png

最终来到

bc46a07652c0bf837d3e00ce8bdd06ba.png

我们看到,此时绑定了端口,用的是java的NIO的socket知识,这里面就涉及到tomcat的IO模型了,BIO,AIO,NIO,NIO2等等,有兴趣可以了解下。

至此主函数load过程基本结束了,最后用一幅图来总结下:

c613f732e48710a2a8a3c32e4d2ed183.png

总结

今天学习的内容较多,也只是把主流程介绍了下,涉及到的细节还需要多动手实践,算是揭开tomcat神秘面纱的起步,接下来还会有start过程分析,一个http请求进来,tomcat是怎么处理的等两篇的内容分析。希望带有兴趣的小伙伴入门。

长按关注,欢迎一起探讨技术

06f6dda940dfa4e5061915d7b1eb0f82.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值