一:Tomcat组成的部分
题外话: 你知道Tomcat、Catalina命名的由来吗?
你知道Tomcat与Apache区别吗?
Tomcat是一个运行Java程序的容器,通过启动startup.bat(bin目录下文件),执行Bootstrap.java下的main()方法,开始启动tomcat容器
public static void main(String args[]) {
if (daemon == null) {
daemon = new Bootstrap();//创建了一个引导对象
try {//引导对象初始化,即创建了Catalina容器
daemon.init();
} catch (Throwable t) {
t.printStackTrace();
return;
}
}
}
继续调用init();创建Catalina对象,这是个核心容器
再继续调用load();方法,实际上是通过反射调用了catalina的load方法。
找到config file(server.xml);然后创建digester,解析server.xml,生成各组件对象(Server、Service、Container、Connector等)以及建立相互之间的关系。
-----------------------------分隔线--------------------------
以上,讲了那么多,好像对Tomcat的架构还是不熟啊,不要慌,先上图
关系是什么呢?
一个汉字对应一个字符,两个字节。而这里是:
一个Tomcat对应一个Server,一个Server(名词)对应多个service(动词),一个Service里面有一个Container和多个Connector。
Are you know? ----> 每个Container容器,又包含4个容器
4个子容器的作用分别是:
(1)Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine;
(2)Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;
(3)Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;
(4)Wrapper:每一Wrapper封装着一个Servlet
Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端,Container处理完请求之后再返回给Connector,最后在由Connector通过Socket将处理的结果返回给客户端,这样整个请求的就处理完了!
可以把Connector分为四个方面进行理解:
(1)Connector如何接受请求的?
(2)如何将请求封装成Request和Response的?
(3)封装完之后的Request和Response如何交给Container进行处理的?
(4)Container处理完之后如何交给Connector并返回给客户端的?
先看图,如下
Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的。
其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
(1)Endpoint用来处理底层Socket的网络连接,Processor用于将Endpoint接收到的Socket封装成Request,Adapter用于将Request交给Container进行具体的处理。
(2)Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。
(3)Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。
至此,我们应该很轻松的回答(1)(2)(3)的问题了,但是(4)还是不知道,那么我们就来看一下Container是如何进行处理的以及处理完之后是如何将处理完的结果返回给Connector的?
Container处理请求是使用Pipeline-Valve管道来处理的!(Valve是阀门之意)
Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将处理后的请求返回,再让下一个处理着继续处理。
二:每部分的作用(可恶,我居然把作用放到下面讲了,应该在介绍完框架之后,就要讲的嘛)
一个Tomcat对应一个Server,掌握整个服务的生死大权。
一个Server(名词)对应多个Service(动词):Service表示对外提供的服务。
一个Service里面有一个Container和多个Connector: Connector接收请求,并将请求封装成Request与Response对象、Container封装和管理Servlet,以及具体处理request请求.
-====================例子
Tomcat Server处理一个http请求的过程
假设来自客户的请求为:
1) 请求被发送到本机端口8080(假设为),被在那里侦听的Coyote HTTP/1.1 Connector获得
(1-1)Connector的主要任务是负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理这个请求的线程
2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应 3) Engine获得请求mp.net/postedit/hello.jsp,匹配它所拥有的所有虚拟主机Host
4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5) localhost Host获得请求/postedit/hello.jsp,匹配它所拥有的所有Context
6) Host匹配到路径为/hello.jsp的Context(如果匹配不到就把该请求交给路径名为”"的Context去处理)
7) path=”/postedit”的Context获得请求/postedit/hello.jsp,在它的mapping table中寻找对应的servlet
8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
10)Context把执行完了之后的HttpServletResponse对象返回给Host
11)Host把HttpServletResponse对象返回给Engine
12)Engine把HttpServletResponse对象返回给Connector
13)Connector把HttpServletResponse对象返回给客户browser