导读 本文适合有基础的小伙伴,如果你对tomcat启动及请求的流程处理不熟悉,可能看起来会比较吃力。有兴趣了解的小伙伴可以参考我之前的博客,希望对你有帮助

​浅谈Tomcat的启动流程(源码级别)​​,浅谈Tomcat接收到一个请求后在其内部的执行流程(源码)​​.

一、整体架构图​​

​​

二、准备工作(tomcat启动)​​

整个准备工作,可以直接理解为一个模板方法模式。

startup.sh

直接启动tomcat时,使用到的shell脚本,该脚本是整个tomcat的启动入口;

LifecycleBase

tomcat为了统一管理tomcat启动过程中相关组件的生命周期,使用了模板方法设计模式。该方法中包含了顶层的接口为Lifecycle,以顶层接口中的init和stop方法为例,LifecycleBase抽象类首先对init和stop方法进行一个基础的过滤,然后继续调用子类的initInternal和stopInternal方法。如果希望向tomcat中添加组件,就可以直接实现LifecycleBase抽象类,然后重写我们希望处理的生命周期的各个方法;

init

初始化需要使用的类加载器(tomcat需要打破双亲委派机制,用来保证应用与应用之间的隔离性)

load

首先按照catalina.java类中配置的标签规则,解析server.xml类中各个标签的数据;然后根据前面的配置信息,初始化相关的组件对象,这里就包含了我们后文所需要的Connector、ProtocolHandler、Pipeline等对象;

start

我们实例化出来的一些组件对象,是用来处理请求的,这里就涉及相关后台线程的开启,该步骤的主要任务也主要就是开启对应的后台线程任务。

​​​​

三、处理请求(后台线程处理)​​​​

整个tomcat是一个大的server组件,每部署一个服务就是一个service组件。整个请求处理组件是基于组合模式,这里涉及了ProtocolHandler、EndPoint、Processor。具体ServletRequest对象数据的转发涉及到适配器模式,这里涉及Container、Adapter

Connector

在tomcat启动阶段,会根据server.xml中如下的标签,选择初始化何种的Connector对象,即完成对protocolHandlerClassName参数的赋值,后期利用反射初始化ProtocolHandler对象

ProtocolHandler

内部含有EndPoint+Processor的组合操作。分别用于解决什么网络IO模型(NIO、APR、JIO),什么应用层协议(HTTP、AJP)。这里就是组合模式的体现

EndPoint

用于通信监听的接口,是具体的 Socket 接收和发送处理器,是对传输层的抽象。每一个EndPoint类中都有一个Acceptor类,用来接收外部发来的请求。

Processor

Processor 用来实现 HTTP/AJP 协议,是对应用层的抽象。Processor 接收来自 EndPoint 的 Socket,读取字节流解析成 Tomcat Request 和 Response 对象,并通过 Adapter 将其提交到容器处理

Adapter

紧接上文, Adapter接收由ProtocolHandler组件处理后的ServletRequest,但由于协议不同,客户端发过来的请求信息也不尽相同,但我们编写的具体的业务代码中的ServletRequest是一个标准的对象。Tomcat的解决办法为使用适配器模式、门面模式,通过CoyoteAdapter 类的service方法,将非标准的ServletRequest对象(org.apache.coyote.ServletRequest)适配为ServletRequest对象(org.apache.catalina.connector),但真正的传递给业务层面的ServletRequest是经过tomcat门面模式处理后符合servlet规范的ServletRequest对象(javax.servlet.ServletRequest)

Container

用来装载东西的容器,在 Tomcat 里,容器就是用来装载 Servlet 的。Tomcat 通过一种分层的架构,使得 Servlet 容器具有很好的灵活性。Tomcat 设计了 4 种容器,分别是 Engine、Host、Context 和 Wrapper。这 4 种容器不是平行关系,而是父子关系。**该部分对象的初始化也是在tomcat启动阶段完成的,这里将所有的组件以内部next属性嵌套的关系完成调用。**这里的四个对象虽然属于父子关系,但是他们的实现方式都是基于一个ValveBase抽象类的模板方法,使用内部的next属性完成父子关系的构建。

  1. Engine:引擎,Servlet 的顶层容器,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine;
  2. Host:虚拟主机,负责 web 应用的部署和 Context 的创建。可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可以部署多个 Web 应用程序;
  3. Context:Web 应用上下文,包含多个 Wrapper,负责 web 配置的解析、管理所有的 Web 资源。一个Context对应一个 Web 应用程序;
  4. Wrapper:表示一个 Servlet,最底层的容器,是对 Servlet 的封装,负责 Servlet 实例的创建、执行和销毁。
// 指定service中的,指定container中的,指定的pipeline中的,第一个需要处理的ValveBase请求过滤实现类
xxx.getService().getContainer().getPipeline().getFirst().invoke(request, response)

原文来自:https://blog.51cto.com/u_15942107/6019516

本文地址:https://www.linuxprobe.com/tomcat-zujian-sujl.html编辑:问题终结者,审核员:逄增宝

Linux命令大全:https://www.linuxcool.com/

Linux系统大全:https://www.linuxdown.com/

红帽认证RHCE考试心得:https://www.rhce.net/