tomcat结构
tomcat结构可以通过conf/server.xml看出来
- Server,为其最顶部容器,代表整个服务器。
- Service,官方文档解释为:是共享数据的一个或多个“连接器(Connectors)”的集合单个“容器”,“Service”本身不是“容器”。
- Connector,连接器:用于处理请求相关,负责根据收到的Http请求报文生成Request对象和Response对象,将封装完成的Request对象和Response交给Container,有Container自组件完成后,在返回给自己,最后返回给客户端。
- Container,容器的接口,一共有4个子接口,Engine,host,Context,Wrapper和一个默认实现类ContainerBase,每一个子接口都有默认的实现类StrandardXXX。
- Engine,引擎:用来管理多个站点,一个Service最多只能由一个Engine。
- HOST,虚拟主机:继承Container,Engine的子组件,处理由Engine发来请求,在把请求发送给Context组件。
- Context,上下文:继承Container,HOST的子组件,根据请求的url发送到不同的servlet的容器中。
Connector分析
功能如下:
1.监听服务端口,读取客户端的请求
2.将请求按照指定的协议进行解析
3.根据请求地址找到对应的Container进行处理
4.将响应返回给客户端
结构如下:
- ProtocolHandler
Connector中的ProtocolHandler用于处理不同的通信协议,Tomcat主要支持HTTP、AJP协议,并且支持BIO、NIO、APR等I/O方式。ProtocolHandler中使用AbstractEndpoint启动Socket监听,并且根据不同的I/O方式进行分类,例如NIO2Endpoint,AprEndpoint等。
Processor用于将Endpoint接受到的Socket封装成Request,Adapter用于将封装好的Request交给Container进行具体处理。也就是说,Endpoint梳理TCP/IP协议,而Processor处理HTTP协议,Adapter将请求适配到Container。
2.映射规则实现
tomcat启动
启动入口,从org.apache.catalina.startup.Boostrap类中main启动。
1.初始化Boostrap:
1.1 调用init方法,初始化classLoader,并用处理好的ClassLoader创建Catalina实例,为后面的Catalina初始化做处理。
1.2 调用load方法,其实是调用catalina的load方法(从系统环境变量、VM参数中读取java.io.tmpdir, 并校验文件夹合法性,解析server.xml信息(反射调用setServer,StandardServer.addService等初始化子组件的方法))
1.2.1.1 catalina里面调用了LifecycleBase的init(默认实际上是调用了StandardServer.initInternal方法),初始化StandardService。
1.2.1.1.1 StandardService.initInternal方法
1.2.1.1.1.1 初始Engine(调用engine.init实际调用StandardEngine.initInternal),其内部同时也调用了ContainerBase.initInternal方法
1.2.1.1.1.2 Executor 初始化
1.2.1.1.1.3 Connector 初始化
1.2.1.1.1.4 mapperListener 初始化
2.启动Boostrap的start与init类似
一个请求的生命周期
假设来自客户的请求为:http://localhost:8080/test/index.jsp
1.请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得;
2.Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应;
3.Engine获得请求localhost:8080/test/index.jsp,匹配它所有虚拟主机Host;
4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机);
5.localhost Host获得请求/test/index.jsp,匹配它所拥有的所有Context;
6.Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为"“的Context去处理);
7.path=”/test"的Context获得请求/index.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;