1.TomCat总体结构
TomCat有两大核心组件:Connector和Container。Connector组件是可以被替换的,一个Container可以对应多个Connector。
多个Connector和一个Container就形成了Service。而Service的生存环境就是Server。所以整个TomCat生命周期由Server控制。
Connector主要负责对外交流,而Container主要处理Connector接受的请求,主要处理内部事务。
Service:
TomCat中Service接口的标准实现类是StandardService,它还实现了Lifecycle接口(后面会提到这个接口)。
重要的两个方法:
1.#setContainer# 设置新的Containner 并将新的Container关联到每个Connector
2.#AddConnector# 设置关联关系(包括Container和Service)然后将新的Connector加入到 Connector数组中
Server:
Server的任务是提供一个接口让其他程序能够访问到这个Service集合,同时维护它包含的所有Service的生命周期。标准实现类是StandardServer
重要的方法:
1.#addService# 与#AddConnector#相似 将新的Service加入到 Service数组中
Lifecycle:
TomCat中组件的生命周期是通过Lifecycle接口来控制的,组件只要继承这一接口并实现其中的方法就可以统一被拥有它的组件控制了。
这样一层一层地直到一个最高级的组件就可以控制TomCat中所有的组件的生命周期了,最高组件就是Server。而控制Server的是Startup,也就是启动和关闭Tomcat。
组件的声明周期由包含它的父组件控制,所以它的Start方法自然就是调用它下面的组件的Start方法,Stop方法也是一样。
以Server的start中的一段代码为例:
1 synchronized(services){2 for(int i = 0 ;i
简单地循环启动所有的Service组件,但是所有的Service必须要实现Lifecycle接口。
stop方法与之类似,不再赘述。
Connector组件
主要任务:负责接收浏览器发过来的TCP连接请求,创建一个Request和Response对象分别用于和请求端交换数据。然后会产生一个线程来处理这个请求并把产生的Request和Response对象传给这个请求的线程,处理这个请求的线程就是Container组件的工作了。
简而言之,Connector最重要的功能就是接收连接请求,然后分配线程让Container来处理这个请求。
code略。
Servlet容器Container
Container容器的设计用的是典型的责任链设计模式,它由4个子容器组件构成,分别是Engine Host Context Wrapper 这四个组件是父子关系
通常一个Servlet class对应一个Wrapper,而多个Wrapper对应一个Context。
Context定义在父容器Host中,Host不是必需的,但是要运行war程序,就必须要用Host,因为在war中必有web.xml文件,这个文件的解析就需要Host。
如果有多个Host就要定义一个top容器Engine,一个Engine就代表了一个完整的Servlet引擎。
Engine容器:之定义了一些基本的关联关系,标准实现类是StandardEngine,没有父容器,添加的子容器只能是Host类型的。
Host容器:一个Host在Engine中代表一个虚拟主机,这个虚拟主机的作用就是运行多个应用,它负责安装和展开这些应用,并且标识这个应用以便能够区分他们。StandardHost除了继承了所有容器都继承的ContainerBase外,StandardHost还实现了Deployer接口,这个接口中的方法可以安装、展开、启动和结束每个Web应用。
Context容器:代表Servlet的Context,具备了Servlet运行的基本环境,理论上只要有Context就能运行Servlet了,简单的Tomcat可以没有Engine和Host。Context最重要的功能就是管理它内部的Servlet实例,Servlet实例在Context中是以Wrapper出现的。
Context的配置文件中有一个reloadable属性,当这个属性设置为true时,war被修改后Tomcat会自动重新加载这个应用。 //热部署
如何实现的热部署?
ContainerBase类中定义了一个内部类ContainerBackgroundProcessor,这个类运行在一个后台线程中,周期地执行run方法,这个run会周期地调用所有容器的backgroundProcess方法,而这个方法中部分代码如下:
if(reloadble && (getLoader().modified())){ .... reload(); //先调用stop方法再调用start方法 简单粗暴完成Context重新加载 .... }
Wrapper容器
重要的方法:
#loadServlet# 在这个方法中装载了Servlet后就会调用Servlet的init方法,同时会传一个StandardWrapperFacade对象(实现了ServletConfig接口)给Servlet。
当Servlet初始化完成后,就等着StandardWrapperValve调用它的Service方法了,调用Service方法之前要调用Servlet所有的Filter。