Tomcat的各级容器们的职责,手把手教你写Java项目文档

// 触发监听事件

support.firePropertyChange(“service”, null, service);

}

}

Server组件还需要启动一个Socket来监听停止端口,所以才能通过shutdown命令关闭Tomcat。

上面Catalina的启动方法最后一行代码就是调用Server#await。

在await方法里会创建一个Socket监听8005端口,并在一个死循环里接收Socket上的连接请求,如果有新的连接到来就建立连接,然后从Socket中读取数据;如果读到的数据是停止命令“SHUTDOWN”,就退出循环,进入stop流程。

Service组件

========================================================================

Service组件的具体实现类StandardService

public class StandardService extends LifecycleBase implements Service {

//名字

private String name = null;

//Server实例

private Server server = null;

//连接器数组

protected Connector connectors[] = new Connector[0];

private final Object connectorsLock = new Object();

//对应的Engine容器

private Engine engine = null;

//映射器及其监听器

protected final Mapper mapper = new Mapper();

protected final MapperListener mapperListener = new MapperListener(this);

StandardService继承了LifecycleBase抽象类,此外StandardService中还有一些我们熟悉的组件,比如Server、Connector、Engine和Mapper。

Tomcat支持热部署,当Web应用的部署发生变化,Mapper中的映射信息也要跟着变化,MapperListener就是监听器,监听容器的变化,并把信息更新到Mapper。

Service启动方法


protected void startInternal() throws LifecycleException {

// 1. 触发启动监听器

setState(LifecycleState.STARTING);

// 2. 先启动Engine,Engine会启动它子容器

if (engine != null) {

synchronized (engine) {

engine.start();

}

}

// 3. 再启动Mapper监听器

mapperListener.start();

// 4.最后启动连接器,连接器会启动它子组件,比如Endpoint

synchronized (connectorsLock) {

for (Connector connector: connectors) {

if (connector.getState() != LifecycleState.FAILED) {

connector.start();

}

}

}

}

Service先后启动Engine、Mapper监听器、连接器。

内层组件启动好了才能对外提供服务,才能启动外层的连接器组件。而Mapper也依赖容器组件,容器组件启动好了才能监听它们的变化,因此Mapper和MapperListener在容器组件之后启动。

Engine组件

=======================================================================

最后我们再来看看顶层的容器组件Engine具体是如何实现的。Engine本质是一个容器,因此它继承了ContainerBase基类,并且实现了Engine接口。

public class StandardEngine extends ContainerBase implements Engine {

}

Engine的子容器是Host,所以它持有了一个Host容器的数组,这些功能都被抽象到了ContainerBase,ContainerBase中有这样一个数据结构:

protected final HashMap<String, Container> children = new HashMap<>();

ContainerBase用HashMap保存了它的子容器,并且ContainerBase还实现了子容器的“增删改查”,甚至连子组件的启动和停止都提供了默认实现,比如ContainerBase会用专门的线程池来启动子容器。

for (int i = 0; i < children.length; i++) {

results.add(startStopExecutor.submit(new StartChild(children[i])));

}

所以Engine在启动Host子容器时就直接重用了这个方法。

Engine自己做了什么?


容器组件最重要的功能是处理请求,而Engine容器对请求的“处理”,其实就是把请求转发给某一个Host子容器来处理,具体是通过Valve来实现的。

每个容器组件都有一个Pipeline,而Pipeline中有一个基础阀(Basic Valve)。

Engine容器的基础阀定义如下:

final class StandardEngineValve extends ValveBase {

public final void invoke(Request request, Response response)

throws IOException, ServletException {

// 拿到请求中的Host容器

Host host = request.getHost();

if (host == null) {

return;

}

// 调用Host容器中的Pipeline中的第一个Valve

host.getPipeline().getFirst().invoke(request, response);

}

}

把请求转发到Host容器。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

同时减轻大家的负担。**
[外链图片转存中…(img-HFfE8okj-1710845483385)]
[外链图片转存中…(img-bQ9N1Cpf-1710845483386)]
[外链图片转存中…(img-z0MuXJL6-1710845483387)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-iA9UuVjq-1710845483387)]

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值