一.Tomcat 基础
1.1.Tomcat 基础
Tomcat?本质上就是一款?Servle(色为)?容器,?因此Catalina(卡塔琳娜)才是?Tomcat?的核心?,?其他模块都是为Catalina(卡塔琳娜)?提供支撑的。?比如?:?通过Coyote?(k有你)模块提供链接通信,Jasper(贾斯珀)?模块提供JSP引擎,Naming?提供JNDI?服务,Juli?提供日志服务。
1).?软件架构
1.?C/S:?客户端/服务器端?‐‐‐‐‐‐‐‐‐‐‐‐>?QQ?,?360?....
2.?B/S:?浏览器/服务器端?‐‐‐‐‐‐‐‐‐‐‐‐>?京东,?网易?,?淘宝?,?传智播客
官网
2).?资源分类
1.?静态资源:?所有用户访问后,得到的结果都是一样的,称为静态资源。静态资
源可以直接被浏览器解析。
*?如:?html,css,JavaScript,jpg
2.?动态资源:?每个用户访问相同资源后,得到的结果可能不一样?,?称为动态资
源。动态资源被访问后,需要先转换为静态资源,再返回给浏览器,通过浏览器进行解析。
*?如:servlet/jsp,php,asp....
3).?网络通信三要素
1.?IP:电子设备(计算机)在网络中的唯一标识。
2.?端口:应用程序在计算机中的唯一标识。?0~65536
3.?传输协议:规定了数据传输的规则
1.?基础协议:
1.?tcp?:?安全协议,三次握手。?速度稍慢
2.?udp:不安全协议。?速度
为什么会有TCP/IP协议?
在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,
这些电脑在表达同一种信息的时候所使用的方法是千差万别。
就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样。
计算机使用者意识到,计算机只是单兵作战并不会发挥太大的作用。
只有把它们联合起来,电脑才会发挥出它最大的潜力。于是人们就
想方设法的用电线把电脑连接到了一起。
但是简单的连到一起是远远不够的,就好像语言不同的两个人互相见了面,
完全不能交流信息。因而他们需要定义一些共通的东西来进行交流,
TCP/IP就是为此而生。TCP/IP不是一个协议,而是一个协议族的统称。
里面包括了IP协议,IMCP协议,TCP协议,
以及我们更加熟悉的http、ftp、pop3协议等等。
电脑有了这些,就好像学会了外语一样,就可以和其他的计算机终端做自由的交流了。
TCP/IP协议分层 TCP/IP协议族按照层次由上到下,层层包装。
应用层:
向用户提供一组常用的应用程序,比如电子邮件、文件传输访问、远程登录等。远程登录TELNET使用TELNET协议提供在网络其它主机上注册的接口。TELNET会话提供了基于字符的虚拟终端。文件传输访问FTP使用FTP协议来提供网络内机器间的文件拷贝功能。
传输层:
提供应用程序间的通信。其功能包括:一、格式化信息流;二、提供可靠传输。为实现后者,传输层协议规定接收端必须发回确认,并且假如分组丢失,必须重新发送。
网络层?:
负责相邻计算机之间的通信。其功能包括三方面。
一、处理来自传输层的分组发送请求,收到请求后,将分组装入IP数据报,填充报头,选择去往信宿机的路径,然后将数据报发往适当的网络接口。
二、处理输入数据报:首先检查其合法性,然后进行寻径--假如该数据报已到达信宿机,则去掉报头,将剩下部分交给适当的传输协议;假如该数据报尚未到达信宿,则转发该数据报。
三、处理路径、流控、拥塞等问题。
网络接口层:
这是TCP/IP软件的最低层,负责接收IP数据报并通过网络发送之,或者从网络上接收物理帧,抽出IP数据报,交给IP层。
IP?是无连接的
IP?用于计算机之间的通信。
IP?是无连接的通信协议。它不会占用两个正在通信的计算机之间的通信线路。这样,IP?就降低了对网络线路的需求。每条线可以同时满足许多不同的计算机之间的通信需要。
通过?IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。
IP?负责将每个包路由至它的目的地。
IP地址
每个计算机必须有一个?IP?地址才能够连入因特网。
每个?IP?包必须有一个地址才能够发送到另一台计算机。
网络上每一个节点都必须有一个独立的Internet地址(也叫做IP地址)。现在,通常使用的IP地址是一个32bit的数字,也就是我们常说的IPv4标准,这32bit的数字分成四组,也就是常见的255.255.255.255的样式。IPv4标准上,地址被分为五类,我们常用的是B类地址。具体的分类请参考其他文档。需要注意的是IP地址是网络号+主机号的组合,这非常重要。
CP/IP?使用?32?个比特来编址。一个计算机字节是?8?比特。所以?TCP/IP?使用了?4?个字节。
一个计算机字节可以包含?256?个不同的值:
00000000、00000001、00000010、00000011、00000100、00000101、00000110、00000111、00001000?.......?直到?11111111。
现在,你知道了为什么?TCP/IP?地址是介于?0?到?255?之间的?4?个数字。
TCP?使用固定的连接
TCP?用于应用程序之间的通信。
当应用程序希望通过?TCP?与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP?将在两个应用程序之间建立一个全双工?(full-duplex)?的通信。
这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。
UDP?和?TCP?很相似,但是更简单,同时可靠性低于?TCP。
IP?路由器
当一个?IP?包从一台计算机被发送,它会到达一个?IP?路由器。
IP?路由器负责将这个包路由至它的目的地,直接地或者通过其他的路由器。
在一个相同的通信中,一个包所经由的路径可能会和其他的包不同。而路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址。
域名
12?个阿拉伯数字很难记忆。使用一个名称更容易。
用于?TCP/IP?地址的名字被称为域名。w3school.com.cn?就是一个域名。
当你键入一个像?http://www.w3school.com.cn?这样的域名,域名会被一种?DNS?程序翻译为数字。
在全世界,数量庞大的?DNS?服务器被连入因特网。DNS?服务器负责将域名翻译为?TCP/IP?地址,同时负责使用新的域名信息更新彼此的系统。
当一个新的域名连同其?TCP/IP?地址一同注册后,全世界的?DNS?服务器都会对此信息进行更新。
TCP/IP
TCP/IP?意味着?TCP?和?IP?在一起协同工作。
TCP?负责应用软件(比如你的浏览器)和网络软件之间的通信。
IP?负责计算机之间的通信。
TCP?负责将数据分割并装入?IP?包,然后在它们到达的时候重新组合它们。
IP?负责将包发送至接受者。
TCP报文格式
16位源端口号:16位的源端口中包含初始化通信的端口。源端口和源IP地址的作用是标识报文的返回地址。
16位目的端口号:16位的目的端口域定义传输的目的。这个端口指明报文接收计算机上的应用程序地址接口。
32位序号:32位的序列号由接收端计算机使用,重新分段的报文成最初形式。当SYN出现,序列码实际上是初始序列码(Initial?Sequence?Number,ISN),而第一个数据字节是ISN+1。这个序列号(序列码)可用来补偿传输中的不一致。
32位确认序号:32位的序列号由接收端计算机使用,重组分段的报文成最初形式。如果设置了ACK控制位,这个值表示一个准备接收的包的序列码。
4位首部长度:4位包括TCP头大小,指示何处数据开始。
保留(6位):6位值域,这些位必须是0。为了将来定义新的用途而保留。
标志:6位标志域。表示为:紧急标志、有意义的应答标志、推、重置连接标志、同步序列号标志、完成发送数据标志。按照顺序排列是:URG、ACK、PSH、RST、SYN、FIN。
16位窗口大小:用来表示想收到的每个TCP数据段的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16字节字段,因而窗口大小最大为65535字节。
16位校验和:16位TCP头。源机器基于数据内容计算一个数值,收信息机要与源机器数值?结果完全一样,从而证明数据的有效性。检验和覆盖了整个的TCP报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的。
16位紧急指针:指向后面是优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充。加快处理标示为紧急的数据段。
选项:长度不定,但长度必须为1个字节。如果没有选项就表示这个1字节的域等于0。
数据:该TCP协议包负载的数据。
在上述字段中,6位标志域的各个选项功能如下。
URG:紧急标志。紧急标志为"1"表明该位有效。
ACK:确认标志。表明确认编号栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。
PSH:推标志。该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理。在处理Telnet或rlogin等交互模式的连接时,该标志总是置位的。
RST:复位标志。用于复位相应的TCP连接。
SYN:同步标志。表明同步序列编号栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。
FIN:结束标志。
TCP三次握手
(1)第一次握手:Client(快了)将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server(色我)收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client(快了)收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server(色我),Server(色我)检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client(快了)与Server(色我)之间可以开始传输数据了。
简单来说,就是
1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。
TCP四次挥手
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:Client发送一个FIN,用来关闭Client(快了)到Server(色我)的数据传送,Client(快了)进入FIN_WAIT_1状态。
(2)第二次挥手:Server(色我)收到FIN后,发送一个ACK给Client(快了),确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server(色我)进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server(色我)到Client(快了)的数据传送,Server(色我)进入LAST_ACK状态。
(4)第四次挥手:Client(快了)收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server(色我),确认序号为收到序号+1,Server(色我)(色我)进入CLOSED状态,完成四次挥手。
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close(可欧的),也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
1.2 Tomcat 目录结构 Tomcat 的主要目录文件如下 :
bin?/?存放Tomcat的启动、停止等批处理脚本文件
startup.bat?,
startup.sh
用于在windows和linux下的启动脚本
shutdown.bat?,
shutdown.sh
用于在windows和linux下的停止脚本
conf?/?用于存放Tomcat的相关配置文件
Catalina?用于存储针对每个虚拟机的Context配置
context.xml
用于定义所有web应用均需加载的Context配
置,如果web应用指定了自己的context.xml
,该文件将被覆盖
catalina.properties?Tomcat?的环境变量配置
catalina.policy?Tomcat?运行的安全策略配置
logging.properties
Tomcat?的日志配置文件,?可以通过该文件修
改Tomcat?的日志级别及日志路径等
server.xml?Tomcat?服务器的核心配置文件
tomcat-users.xml?定义Tomcat默认的用户及角色映射信息配置
web.xml
Tomcat?中所有应用默认的部署描述文件,?主
要定义了基础Servlet和MIME映射。
lib?/?Tomcat?服务器的依赖包
logs?/?Tomcat?默认的日志存放目录
webapps?/?Tomcat?默认的Web应用部署目录
work?/?Web?应用JSP代码生成和编译的临时目录
二.Tomcat 架构 2.1 Http工作原理
HTTP协议是浏览器与服务器之间的数据传送协议。作为应用层协议,HTTP是基于TCP/IP
协议来传递数据的(HTML文件、图片、查询结果等),HTTP协议不涉及数据包
(Packet)传输,主要规定了客户端和服务器之间的通信格式。
从图上你可以看到,这个过程是:
1)?用户通过浏览器进行了一个操作,比如输入网址并回车,或者是点击链接,接着浏览
器获取了这个事件。
2)?浏览器向服务端发出TCP连接请求。
3)?服务程序接受浏览器的连接请求,并经过TCP三次握手建立连接。
4)?浏览器将请求数据打包成一个HTTP协议格式的数据包。
5)?浏览器将该数据包推入网络,数据包经过网络传输,最终达到端服务程序。
6)?服务端程序拿到这个数据包后,同样以HTTP协议格式解包,获取到客户端的意图。
7)?得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果。
8)?服务器将响应结果(可能是HTML或者图片等)按照HTTP协议格式打包。
9)?服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器。
10)?浏览器拿到数据包后,以HTTP协议的格式解包,然后解析数据,假设这里的数据是
HTML。
11)?浏览器将HTML文件展示在页面上。
那我们想要探究的Tomcat作为一个HTTP服务器,在这个过程中都做了些什么事情呢?主
要是接受连接、解析请求数据、处理请求和发送响应这几个步骤。
2.2 Http服务器请求处理
浏览器发给服务端的是一个HTTP格式的请求,HTTP服务器收到这个请求后,需要调用服 务端程序来处理,所谓的服务端程序就是你写的Java类,一般来说不同的请求需要由不同 的Java类来处理。
1)?图1?,?表示HTTP服务器直接调用具体业务类,它们是紧耦合的。
2)?图2,HTTP服务器不直接调用业务类,而是把请求交给容器来处理,容器通过
Servlet(色为的)接口调用业务类。因此Servlet(色为的)接口和Servlet(色为的)容器的出现,达到了HTTP服务器与
业务类解耦的目的。而Servlet(色为的)接口和Servlet(色为的)容器这一整套规范叫作Servlet(色为的)规范。
Tomcat按照Servlet(色为的)规范的要求实现了Servlet(色为的)容器,同时它们也具有HTTP服务器的功
能。作为Java程序员,如果我们要实现新的业务功能,只需要实现一个Servlet(色为的),并把它
注册到Tomcat(Servlet容器)中,剩下的事情就由Tomcat帮我们处理了。
三. Servlet容器工作流程
为了解耦,HTTP服务器不直接调用Servlet(色为的),而是把请求交给Servlet(色为的)容器来处理,那
Servlet(色为的)容器又是怎么工作的呢?
当客户请求某个资源时,HTTP服务器会用一个ServletRequest(色为的?为快的)对象把客户的请求信息封
装起来,然后调用Servlet(色为的)容器的service(色为的)方法,Servlet(色为的)容器拿到请求后,根据请求的URL
和Servlet(色为的)的映射关系,找到相应的Servlet(色为的),如果Servlet(色为的)还没有被加载,就用反射机制创
建这个Servlet(色为的),并调用Servlet(色为的)的init(in?奶的)方法来完成初始化,接着调用Servlet(色为的)的service(色为的)方法
来处理请求,把ServletResponse(色为的?瑞邦的)对象返回给HTTP服务器,HTTP服务器会把响应发送给
客户端。
四Tomcat整体架构
我们知道如果要设计一个系统,首先是要了解需求,我们已经了解了Tomcat要实现两个 核心功能: 1) 处理Socket(少改)连接,负责网络字节流与Request(瑞快死的)和Response(瑞死榜死)对象的转化。 2) 加载和管理Servlet(色为的),以及具体处理Request(瑞快死的)请求。 因此Tomcat设计了两个核心组件连接器(Connector)(可耐的)和容器(Container)(可提热)来分别做这 两件事情。连接器负责对外交流,容器负责内部处理。 五连接器 - Coyote(k有你)
Coyote(k有你)?是Tomcat的连接器框架的名称?,?是Tomcat服务器提供的供客户端访问的外部接
口。客户端通过Coyote(k有你)与服务器建立连接、发送请求并接受响应?。
Coyote?封装了底层的网络通信(Socket(少改)?请求及响应处理),为Catalina(卡?塔?
琳娜)容器提供了统一的接口,使Catalina(卡塔琳娜)容器与具体的请求协议及IO操作方式完全解耦。Coyote(k有你)?将Socket(少改)?输
入转换封装为?Request?(瑞快死的)对象,交由Catalina(卡?塔?琳娜)?容器进行处理,处理请求完成后,?Catalina(卡塔琳娜)?通
过Coyote(k有你)?提供的Response(瑞死榜死)?对象将结果写入输出流?。
Coyote?(k有你)作为独立的模块,只负责具体协议和IO的相关操作,?与Servlet(色为的)?规范实现没有直
接关系,因此即便是?Request(瑞快死的)?和?Response(瑞死榜死)?对象也并未实现Servlet(色为的)规范对应的接口,?而
是在Catalina?中将他们进一步封装为ServletRequest(色为的?为快的)?和?ServletResponse(色为的?瑞邦的)?。
六.IO模型与协议
在Coyote(k有你)中?,?Tomcat支持的多种I/O模型和应用层协议,具体包含哪些IO模型和应用层
协议,请看下表:
Tomcat?支持的IO模型(自8.5/9.0?版本起,Tomcat?移除了?对?BIO?的支持):
北京市昌平区建材城西路金燕龙办公楼一层?电话:400-618-9090
IO模型
描述
NIO?非阻塞I/O,采用Java?NIO类库实现。
NIO2?异步I/O,采用JDK?7最新的NIO2类库实现。
APR
采用Apache可移植运行库实现,是C/C++编写的本地库。如果选择该方案,需要单独安装APR库。
应用层协
议
描述
HTTP/1.1?这是大部分Web应用采用的访问协议。
AJP
用于和Web服务器集成(如Apache),以实现对静态资源的优化以及集群部署,当前支持AJP/1.3。
HTTP/2
HTTP?2.0大幅度的提升了Web性能。下一代HTTP协议?,?自8.5以及9.0版本之后支持。
Tomcat?支持的应用层协议?:
协议分层?:
在?8.0?之前?,?Tomcat?默认采用的I/O方式为?BIO?,?之后改为?NIO。?无论?NIO、NIO2还是?APR,?在性能方面均优于以往的BIO。?如果采用APR,?甚至可以达到?Apache?HTTP
Server(色为的)?的影响性能。
Tomcat为了实现支持多种I/O模型和应用层协议,一个容器可能对接多个连接器,就好比
一个房间有多个门。但是单独的连接器或者容器都不能对外提供服务,需要把它们组装
起来才能工作,组装后这个整体叫作Service组件。这里请你注意,Service本身没有做什
么重要的事情,只是在连接器和容器外面多包了一层,把它们组装在一起。Tomcat内可
能有多个Service(色为的),这样的设计也是出于灵活性的考虑。通过在Tomcat中配置多个
Service(色为的),可以实现通过不同的端口号来访问同一台机器上部署的不同应用。
连接器组件 连接器中的各个组件的作用如下:
EndPoint(an保)
1)?EndPoint(an保)?:?Coyote(k有你)?通信端点,即通信监听的接口,是具体Socket(少改)接收和发送处理
器,是对传输层的抽象,因此EndPoint(Abstract)用来实现TCP/IP协议的。
2)?Tomcat?并没有EndPoint(an保)?接口,而是提供了一个抽象类AbstractEndpoint?(阿的死抓的an保)
义了两个内部类:Acceptor和SocketProcessor。Acceptor用于监听Socket连接请求。
SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里
调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到
线程池来执行。而这个线程池叫作执行器(Executor),我在后面的专栏会详细介绍
Tomcat如何扩展原生的Java线程池。
Processor(卡死的)
Processor?:?Coyote?协议处理接口?,如果说EndPoint是用来实现TCP/IP协议的,那么
Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解
析成Tomcat?Request和Response对象,并通过Adapter将其提交到容器处理,
Processor是对应用层协议的抽象。
ProtocolHandler(跑的考?寒的热)
ProtocolHandler:?Coyote?协议接口,?通过Endpoint?和?Processor?,?实现针对具体协
议的处理能力。Tomcat?按照协议和I/O?提供了6个实现类?:?AjpNioProtocol?,
AjpAprProtocol,?AjpNio2Protocol?,?Http11NioProtocol?,Http11Nio2Protocol?,
Http11AprProtocol。我们在配置tomcat/conf/server.xml?时?,?至少要指定具体的
ProtocolHandler?,?当然也可以指定协议名称?,?如?:?HTTP/1.1?,如果安装了APR,那么
将使用Http11AprProtocol?,?否则使用?Http11NioProtocol?。
Adapter(阿宝的热)
由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类
来“存放”这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat?Request类。
但是这个Request对象不是标准的ServletRequest,也就意味着,不能用Tomcat
Request作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是
适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是Tomcat
Request对象,CoyoteAdapter负责将Tomcat?Request转成ServletRequest,再调用容
器的Service方法。
七.Catalina(卡塔琳娜) 结构
?Catalina(卡塔琳娜)?的主要组件结构如下:
Catalina(卡塔琳娜)
负责解析Tomcat的配置文件?,?以此来创建服务器Server(色为的)组件,并根据
命令来对其进行管理
Server(色为的)
服务器表示整个Catalina?Servlet(色为的)容器以及其它组件,负责组装并启动
Servlet(色为的)引擎,Tomcat连接器。Server通过实现Lifecycle(饿来的色扣
接口,提供了
一种优雅的启动和关闭整个系统的方式
Service(色为的)
服务是Server(色为的)内部的组件,一个Server(色为的)包含多个Service。它将若干个
Connector(可耐的)
组件绑定到一个Container(可提的)上
Connector(可耐的)
连接器,处理与客户端的通信,它负责接收客户请求,然后转给相关
的容器处理,最后向客户返回响应结果
Container(可提的)?容器,负责处理用户的servlet请求,并返回对象给web用户的模块
Container(可提的)?结构
Tomcat设计了4种容器,分别是Engine、Host、Context和Wrapper。这4种容器不是平
行关系,而是父子关系。,?Tomcat通过一种分层的架构,使得Servlet容器具有很好的灵
活性。
各个组件的含义?:
Engine(嗯经)
表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service
最多只能有一个Engine,但是一个引擎可包含多个Host
Host(厚死的)
代表一个虚拟主机,或者说一个站点,可以给Tomcat配置多个虚拟主
机地址,而一个虚拟主机下可包含多个Context
Context(康text)
表示一个Web应用程序,?一个Web应用可包含多个Wrapper
Wrapper?(喔报
表示一个Servlet,Wrapper?作为容器中的最底层,不能包含子容器
我们也可以再通过Tomcat的server.xml配置文件来加深对Tomcat容器的理解。Tomcat
采用了组件化的设计,它的构成组件都是可配置的,其中最外层的是Server,其他组件
按照一定的格式要求配置在这个顶层容器中。
那么,Tomcat是怎么管理这些容器的呢?你会发现这些容器具有父子关系,形成一个树
形结构,你可能马上就想到了设计模式中的组合模式。没错,Tomcat就是用组合模式来
管理这些容器的。具体实现方法是,所有容器组件都实现了Container接口,因此组合模
式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的
是最底层的Wrapper,组合容器对象指的是上面的Context、Host或者Engine。
八Tomcat 启动流程
?步骤?:
1)?启动tomcat?,?需要调用?bin/startup.bat?(在linux?目录下?,?需要调用?bin/startup.sh)
,?在startup.bat?脚本中,?调用了catalina.bat。
2)?在catalina.bat?脚本文件中,调用了BootStrap?中的main方法。
3)在BootStrap?的main?方法中调用了?init?方法?,?来创建Catalina?及?初始化类加载器。
4)在BootStrap?的main?方法中调用了?load?方法?,?在其中又调用了Catalina的load方
法。
5)在Catalina?的load?方法中?,?需要进行一些初始化的工作,?并需要构造Digester?对象,?用
于解析?XML。
6)?然后在调用后续组件的初始化操作?。。。
加载Tomcat的配置文件,初始化容器组件?,监听对应的端口号,?准备接受客户端请求
Lifecycle
由于所有的组件均存在初始化、启动、停止等生命周期方法,拥有生命周期管理的特
性,?所以Tomcat在设计的时候,?基于生命周期管理抽象成了一个接口?Lifecycle?,而组
件?Server、Service、Container、Executor、Connector?组件?,?都实现了一个生命周期
的接口,从而具有了以下生命周期中的核心方法:
1)?init():初始化组件??in耐的
2)?start():启动组件???死导的
3)?stop():停止组件????死导
4)?destroy():销毁组件??滴死导
各组件的默认实现
上面我们提到的Server、Service、Engine、Host、Context都是接口,?下图中罗列了这
些接口的默认实现类。当前对于?Endpoint组件来说,在Tomcat中没有对应的Endpoint
接口,?但是有一个抽象类?AbstractEndpoint?,其下有三个实现类:?NioEndpoint、
Nio2Endpoint、AprEndpoint?,?这三个实现类,分别对应于前面讲解链接器?Coyote
时,?提到的链接器支持的三种IO模型:NIO,NIO2,APR?,?Tomcat8.5版本中,默认采
用的是?NioEndpoint(牛的按?跑in的
上面我们提到的Server、Service、Engine、Host、Context都是接口,?下图中罗列了这
些接口的默认实现类。当前对于?Endpoint组件来说,在Tomcat中没有对应的Endpoint
接口,?但是有一个抽象类?AbstractEndpoint?,其下有三个实现类:?NioEndpoint、
Nio2Endpoint、AprEndpoint?,?这三个实现类,分别对应于前面讲解链接器?Coyote
时,?提到的链接器支持的三种IO模型:NIO,NIO2,APR?,?Tomcat8.5版本中,默认采
用的是?NioEndpoint。牛的按?跑in的
九Tomcat 请求处理流程
请求流程
设计了这么多层次的容器,Tomcat是怎么确定每一个请求应该由哪个Wrapper(喔爆)
容器里的
Servlet来处理的呢?答案是,Tomcat是用Mapper(买普
组件来完成这个任务的。
Mapper组件的功能就是将用户请求的URL定位到一个Servlet,它的工作原理是:
Mapper组件里保存了Web应用的配置信息,其实就是容器组件与访问路径的映射关系,
比如Host容器里配置的域名、Context容器里的Web应用路径,以及Wrapper容器里
Servlet映射的路径,你可以想象这些配置信息就是一个多层次的Map。
当一个请求到来时,Mapper组件通过解析请求URL里的域名和路径,再到自己保存的
Map里去查找,就能定位到一个Servlet。请你注意,一个请求URL最后只会定位到一个
Wrapper容器,也就是一个Servlet。
下面的示意图中?,?就描述了?当用户请求链接?http://www.itcast.cn/bbs/findAll?之
后,?是如何找到最终处理业务逻辑的servlet?。
那上面这幅图只是描述了根据请求的URL如何查找到需要执行的Servlet?,?那么下面我们
再来解析一下?,?从Tomcat的设计架构层面来分析Tomcat的请求处理。
步骤如下:
1)?Connector(可耐的)组件Endpoint(and?跑赢)中的Acceptor监听客户端套接字连接并接收Socket(少改的)。
2)?将连接交给线程池Executor(in的热k的)处理,开始执行请求响应任务。
3)?Processor(跑卡死)组件读取消息报文,解析请求行、请求体、请求头,封装成Request(瑞快死的)对象。
4)?Mapper(买普)组件根据请求行的URL值和请求头的Host值匹配由哪个Host容器、Context(康text的)容
器、Wrapper(我爆)容器处理请求。
5)?CoyoteAdaptor(可有你按的打死的)组件负责将Connector(可耐的)组件和Engine(嗯经)容器关联起来,把生成的
Request(瑞快死的)对象和响应对象Response(瑞死榜死)传递到Engine(嗯经)容器中,调用?Pipeline(拍不按的)。
6)?Engine(嗯经)容器的管道开始处理,管道中包含若干个Valve、每个Valve负责部分处理逻
辑。执行完Valve后会执行基础的?Valve--StandardEngineValve,负责调用Host容器的
Pipeline(拍不按的)。
7)?Host容器的管道开始处理,流程类似,最后执行?Context容器的Pipeline(拍不按的)。
8)?Context容器的管道开始处理,流程类似,最后执行?Wrapper容器的Pipeline(拍不按的)。
9)?Wrapper容器的管道开始处理,流程类似,最后执行?Wrapper容器对应的Servlet对象
的?处理方法。
在Tomcat中定义了Pipeline?(拍不按的)和?Valve?两个接口,Pipeline?(拍不按的)用于构建责任链,?后者代表责
任链上的每个处理器。Pipeline(拍不按的)?中维护了一个基础的Valve,它始终位于Pipeline的末端
(最后执行),封装了具体的请求处理和输出响应的过程。当然,我们也可以调用
addValve()方法,?为Pipeline?(拍不按的)添加其他的Valve,?后添加的Valve?位于基础的Valve之
前,并按照添加顺序执行。Pipiline(拍不按的)通过获得首个Valve来启动整合链条的执行?。
十.Jasper
Jasper(接死跑
简介
对于基于JSP?的web应用来说,我们可以直接在JSP页面中编写?Java代码,添加第三方的
标签库,以及使用EL表达式。但是无论经过何种形式的处理,最终输出到客户端的都是
标准的HTML页面(包含js?,css...),并不包含任何的java相关的语法。?也就是说,?我
们可以把jsp看做是一种运行在服务端的脚本。?那么服务器是如何将?JSP页面转换为
HTML页面的呢?
Jasper模块是Tomcat的JSP核心引擎,我们知道JSP本质上是一个Servlet。Tomcat使用
Jasper对JSP语法进行解析,生成Servlet并生成Class字节码,用户在进行访问jsp时,会
访问Servlet,最终将访问的结果直接响应在浏览器端?。另外,在运行的时候,Jasper还
会检测JSP文件是否修改,如果修改,则会重新编译JSP文件。
JSP 编译方式
Tomcat?并不会在启动Web应用的时候自动编译JSP文件,?而是在客户端第一次请求时,
才编译需要访问的JSP文件。
创建一个web项目,?并编写JSP代码?:
<%@?page?import="java.text.DateFormat"?%>
<%@?page?import="java.text.SimpleDateFormat"?%>
<%@?page?import="java.util.Date"?%>
<%@?page?contentType="text/html;charset=UTF‐8"?language="java"?%>
<%@?taglib?prefix="c"?uri="http://java.sun.com/jsp/jstl/core"?%>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
DateFormat?dateFormat?=?new?SimpleDateFormat("yyyy‐MM‐dd
HH:mm:ss");
String?format?=?dateFormat.format(new?Date());
%>
Hello?,?Java?Server?Page?。。。。
<br/>
<%=?format?%>
</body>
</html>
编译过程
Tomcat 在默认的web.xml 中配置了一个org.apache.jasper.servlet.JspServlet,用于处理所有的.jsp 或 .jspx 结尾的请求,该Servlet 实现即是运行时编译的入口。
Tomcat?在默认的web.xml?中配置了一个org.apache.jasper.servlet.JspServlet,用于处
理所有的.jsp?或?.jspx?结尾的请求,该Servlet?实现即是运行时编译的入口。