Tomcat源码学习探索笔记

如今tomcat源码量很是大,想读懂那么多人写的代码很耗时间,这里记下我学习tomcat的一点笔记java

TomcatWeb服务器git

几个月前我本科没毕业的时候,还不知道web服务器和应用服务器的区别github

用我本身的话描述,本身的程序里带jar文件来支持JavaEE组件的是web服务器web

socket开始bootstrap

我以为不少中间件源码读起来很困难,由于咱们只看到了最终的产品,中间发展的过程以及增长的功能咱们并不清楚.浏览器

Tomcat如今的源码量至关的大,即便读一些解读的文章再调试也不容易理解透彻,并且在业务团队里也不必死抠每一个技术细节,因此我以为应该按部就班tomcat

我先写一个最简单的Socket,启动时只要用浏览器访问 localhost:8080 就能够看到socket 传来的信息,并能看返回当前系统时间
收到的消息
 
服务器

返回的结果

多线程

Socket改进app

一个socket虽然很简单,但咱们能够明白HTTP协议的原理

若是咱们把它改进一下,input封装到Request,output封装到response,就好理解多了

我在github上找到一个挺有意思的东东

https://github.com/dasanjos/java-WebServer

我稍微改动了一下这个代码,让它变得更直观些

它就是把我上面写的代码改为线程池管理,并把socket经过handler传给线程,分为RequestResponse,支持了本地文件的读写
 

RequestHandler处理过程
 

执行效果

虽然和上面的代码相比不过就是封装了一下罢了

但线程池把socket监听请求以及io流的处理给分开了,其实这个过程就是tomcatconnectorcontainer经过HttpProcessor传递socket的过程的简化,Main里管线程池的代码咱们能够封装到一个叫Connector里面,有请求就从池子里取个线程,让它合成RequestResponse,把它上交给.....容器

Classloader原理

其实作到上一步,基本能够把这坨代码当webServer跑了,但它不支持servlet,也没有webapps目录和Context,并且咱们都是打war包的,war包里的那些类tomcat是怎么调用的?

由于tomcatclassloader是封装到Context里面的,这个加载过程很差解释,我就写一个简单的例子说明一下:

这个目录结构至关简单,folder下有个编译好的B,咱们启动tomcat而后启动服务的过程能够视为Main类跑时把B类也加载进去


为了更有说服力,咱们能够先ps -ef|grep java 肯定 folder不在咱们的classpath里面

而后VM参数加上-verbose:class 亲眼看看B这个class文件是怎么被加载进去的


在学校的时候配java环境变量,老是要把rt.jar 这堆玩意加到classpath,时间久了基本背下来要加哪些包了

Javaclassloader分为 bootstrap classloader,extension classloadersystem classloader,其实rt.jar里的那些java核心类就是bootstrap classloader给加进去的,咱们能够执行如下这个代码看看bootstrap classloader都加载了什么


Tomcat结构

写了这么多却一直没提tomcat有些三纸无驴的感受,但其实写到这里,咱们本身就能写个很是粗陋的支持servletwebServer相似物了

我学习tomcat源码不只是由于好奇,为了方便定位问题,也是为了了解一点它的设计思想

我画了个草图,并按本身当即标注了一下这些组件是干啥的,大体说明一下tomcat的结构


固然,这里面还有一些Loader, Pipeline ,Valve ,Repository 这类的小东西我没标,否则图就太乱了

由一个Socket忽然变得这么复杂稍微有点过分不天然,也不要紧,我在万能的github上又找到一个过分天然的项目

https://github.com/luminocean/Tommycat

这个项目麻雀虽小五脏俱全,虽然没Server.xml配置文件,tomcat该有的它基本都有,只是容器只有ContextWrapper,但看懂这个基本就明白tomcat的设计思想了

这个项目下面有个Mushroom的项目,主项目跑起来,会把Mushroom放到Context容器里,并经过Loader加载里面编译好的class

这里没有filter,因此若是访问的uri直接能找到文件就直接返回文件内容,找不到就会从ContextValvemap里找加载好的Servlet而后invoke调用

这里面还有个LifeCycle接口,就是我们常说的生命周期,每一个容器都实现了这个接口里的方法

我读源码的办法

我是先debug,debug边看涉及到的类结构,由于这是多线程的,单纯debug不是很好理解

我把主要的类抠出来,只保留类里重要的域,debug一遍就能明白类之间的调用关系

相关文章
相关标签/搜索