深入剖析Tomcat(十三) Host、Engine 容器

前面很多篇文章都在介绍Context与Wrapper两个容器,因为这两个容器确实也比较重要,与我们日常开发也息息相关,但是Catalina是存在四个容器的,这一章就来简单看看Host与Engine这两个容器。

再次展示下Catalina的容器结构,Engine为最顶层的容器,父容器与子容器为一对多的关系,最底层的容器为Wrapper容器,Wrapper容器不再拥有子容器。

Context容器代表一个Web应用,Wrapper容器代表Web应用中的一个servlet,那么Host与Engine代表啥呢,下面通过梳理Engine、Host与Context三者的关系来说明一下。

Host容器与Context容器

一个Tomcat中可以布有多个Web应用,也就是可以有多个Context容器实例。至于如何将请求分发到指定Context中,则是Host容器的任务了。StandardHost类是Host容器的标准实现。

下面通过一张图来展示下Host容器寻址Context容器的过程

根据uri去匹配Context容器的逻辑是一个循环判断的逻辑,代码在StandardHost#map() 方法中,下面是精简后的代码

public Context map(String uri) {Context context = null;String mapuri = uri;while (true) {context = (Context) findChild(mapuri);if (context != null) {break;}int slash = mapuri.lastIndexOf('/');if (slash < 0) {break;}mapuri = mapuri.substring(0, slash);}// 如果没有匹配上就用默认的Contextif (context == null) {context = (Context) findChild("");}return (context);}

假如请求的uri是【/app1/Primitive】,那么拿uri去匹配Context的步骤是这样的

  1. 先拿“/app1/Primitive”去匹配,没有匹配上
  2. 去掉最后的一个“/”后面的内容,uri变为“/app1”,再去匹配,匹配上了,拿到结果

如果最终也没有匹配上,就取默认的Context来用,默认Context在children中的key为空字符串。像我们使用SpringBoot开发项目的话,项目针对的Context在Host children中的key就为空字符串。

书中源码给了一个以Host为顶级容器的示例,我将启动类展示出来,感兴趣的可以下源码来自己试试

package ex13.pyrmont.startup;//explain Hostimport ex13.pyrmont.core.SimpleContextConfig;
import org.apache.catalina.*;
import org.apache.catalina.connector.http.HttpConnector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.loader.WebappLoader;public final class Bootstrap1 {public static void main(String[] args) {//invoke: http://localhost:8080/app1/Primitive or http://localhost:8080/app1/ModernSystem.setProperty("catalina.base", System.getProperty("user.dir"));Connector connector = new HttpConnector();Wrapper wrapper1 = new StandardWrapper();wrapper1.setName("Primitive");wrapper1.setServletClass("PrimitiveServlet");Wrapper wrapper2 = new StandardWrapper();wrapper2.setName("Modern");wrapper2.setServletClass("ModernServlet");Context context = new StandardContext();// StandardContext's start method adds a default mappercontext.setPath("/app1");context.setDocBase("app1");context.addChild(wrapper1);context.addChild(wrapper2);LifecycleListener listener = new SimpleContextConfig();((Lifecycle) context).addLifecycleListener(listener);Host host = new StandardHost();host.addChild(context);host.setName("localhost");host.setAppBase("webapps");Loader loader = new WebappLoader();context.setLoader(loader);// context.addServletMapping(pattern, name);context.addServletMapping("/Primitive", "Primitive");context.addServletMapping("/Modern", "Modern");connector.setContainer(host);try {connector.initialize();((Lifecycle) connector).start();((Lifecycle) host).start();// make the application wait until we press a key.System.in.read();((Lifecycle) host).stop();} catch (Exception e) {e.printStackTrace();}}
}

Engine容器与Host容器

host,顾名思义,url中的host可以是域名也可以是ip。Host容器对应的也就是url中的host,每个Host容器实例都被安排接收其对应的“url中带有相关host的请求”。至于如何将一个请求分发到指定Host容器实例中,则是Engine容器的任务了,Engine容器是顶层容器,它不会再有父容器。StandardEngine类是Engine容器的标准实现。

如果Engine容器作为顶层容器的话,连接器则与Engine容器做关联,一个请求进来后,连接器则会将请求抛入Engine的invoke()方法,Engine再将请求给到指定的Host,Host再给到指定的Context,Context再给到指定的Wrapper,层层流转下来,请求就到达了指定的servlet中,servlet会对请求进行处理与反馈,然后将反馈结果层层上抛,最终给到连接器,连接器将结果返回给客户端,一个请求的寻址与处理流程就完成了。

我们通过一张图来展示下Engine容器寻址Host容器的过程

简单来说就是解析请求url中的host字符串,然后拿这个host字符串当做Host实例的name去 子容器map集合 "children" 中去匹配Host容器实例,匹配不上的话就用默认Host,默认Host一般为key=localhost 的这个Host。用SpringBoot开发的项目中就只有一个 key为 localhsot 的Host实例,默认Host也是它。

书中源码给了一个以Engine为顶级容器的示例,我将启动类展示出来,感兴趣的可以下源码来自己试试

package ex13.pyrmont.startup;//Use engineimport ex13.pyrmont.core.SimpleContextConfig;
import org.apache.catalina.*;
import org.apache.catalina.connector.http.HttpConnector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.loader.WebappLoader;public final class Bootstrap2 {public static void main(String[] args) {//invoke: http://localhost:8080/app1/Primitive or http://localhost:8080/app1/ModernSystem.setProperty("catalina.base", System.getProperty("user.dir"));Connector connector = new HttpConnector();Wrapper wrapper1 = new StandardWrapper();wrapper1.setName("Primitive");wrapper1.setServletClass("PrimitiveServlet");Wrapper wrapper2 = new StandardWrapper();wrapper2.setName("Modern");wrapper2.setServletClass("ModernServlet");Context context = new StandardContext();// StandardContext's start method adds a default mappercontext.setPath("/app1");context.setDocBase("app1");context.addChild(wrapper1);context.addChild(wrapper2);LifecycleListener listener = new SimpleContextConfig();((Lifecycle) context).addLifecycleListener(listener);Host host = new StandardHost();host.addChild(context);host.setName("localhost");host.setAppBase("webapps");Loader loader = new WebappLoader();context.setLoader(loader);// context.addServletMapping(pattern, name);context.addServletMapping("/Primitive", "Primitive");context.addServletMapping("/Modern", "Modern");Engine engine = new StandardEngine();engine.addChild(host);engine.setDefaultHost("localhost");connector.setContainer(engine);try {connector.initialize();((Lifecycle) connector).start();((Lifecycle) engine).start();// make the application wait until we press a key.System.in.read();((Lifecycle) engine).stop();} catch (Exception e) {e.printStackTrace();}}
}

Engine与Host 两个容器的主要内容就是上面这些,涉及到的类也是容器老生常谈的几种类,容器标准实现类 StandardEngine,StandardHost;容器Pipeline的基础阀 StandardEngineValve,StandardHostValve;容器相关的映射器 StandardEngineMapper,StandardHostMapper,这些映射器在Tomcat4中还存在,现在使用的Tomcat版本已经不存在这些映射器了,根据请求获取Host、Context的这些逻辑都放在了request对象中来实现了。想看看源码的看看这几个类就行。

本章内容就介绍到这里,Engine与Host两个容器的功能与我们的开发工作 关联并不太多,我们了解其工作方式即可。

源码分享

https://gitee.com/huo-ming-lu/HowTomcatWorks

这一篇在源码中有两个示例,感兴趣的同学可以自己运行看看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/861768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS2022(Visual Studio 2022)最新安装教程

1、下载 1、下载地址 - 官网地址&#xff1a;下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux - 根据自己的电脑的 【操作系统】 灵活选择。 2、安装包 【此处为Windows系统安装包】 2、安装 1、打开软件 - 右击【以管理员身份打开】&#xff0c; 2、准备配置 …

Web Serial串口通信实现WEB浏览器读写M1卡

本示例使用的设备&#xff1a;RS232串口RFID NFC IC卡读写器可二次开发编程发卡器USB转COM-淘宝网 (taobao.com) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> &l…

前端面试题-token的存放位置

哈喽小伙伴们大家好,本系列是一个专门针对前端开发岗的面试题系列,每周将会不定期分享一些面试题,希望对大家有所帮助. 面试官:token 一般在客户端存在哪儿 求职者:Token一般在客户端存在以下几个地方&#xff1a; (1)Cookie&#xff1a;Token可以存储在客户端的Cookie中。服…

61.应交税费的明细科目-待转销项税额

目录 1.变化 2.定义 3.科目设置的目的 4.会计处理 5.会计分录 1.变化 财会2016年22号文--《增值税会计处理规定》中对于应交税费的会计处理有了重大变化&#xff0c;引入了“待转销项税额”这一二级明细科目来核算一般纳税人销售货物、加工修理修配劳务、服务、无形资产…

优思学院|工厂的部门架构管理与精益生产

工厂内有不同部门&#xff0c;各部门之间必须协调合作才能发挥整体功能。工厂最主要的部分是制造产品的现场&#xff0c;这里安装了生产工具&#xff0c;还有操作员进行加工或生产制造。 制造时使用的材料或零组件&#xff0c;需要对外采购。对于加工组装型的工厂&#xff0c;…

短视频利器 ffmpeg (1)

使用FFmpeg切片视频有多种好处&#xff0c;尤其是在处理流媒体内容和优化视频分发时。以下是一些主要优点&#xff1a; 提高流媒体性能&#xff1a; 1、快速启动&#xff1a; 切片允许客户端更快地开始播放视频&#xff0c;因为它不需要等待整个文件下载完毕。客户端可以请求…

基于Boost和平均电流控制方法的APFC电路设计

通过学习无线充电相关知识&#xff0c;为更快熟悉APFC工作原理&#xff0c;通过实验得以掌握 技术要求&#xff1a; 1&#xff09;输入电压&#xff1a;AC 85V&#xff5e;265V&#xff1b; 2&#xff09;输出电压&#xff1a;400V1%&#xff1b; 3&#xff09;输出额定电流…

AI推介-信息抽取(information extraction,IE)论文速览(arXiv方向):2024.04.15-2024.06.01

文章目录~ 1.GAMedX: Generative AI-based Medical Entity Data Extractor Using Large Language Models2.Retrieval Augmented Structured Generation: Business Document Information Extraction As Tool Use3.BioBERT-based Deep Learning and Merged ChemProt-DrugProt for…

音视频开发30 FFmpeg 视频编码- 流程以及重要API,H264编码原理说明,该章节使用h264编码说明

一.H264编码原理 1 视频为什么需要进行编码压缩 ◼ 一张为 720x480 的图像&#xff0c;用 YUV420P 的格式来表示&#xff0c;其大小为&#xff1a; 720*480*1.5 约等于 0.5MB 。 ◼ 如果是 25 帧&#xff0c; 10 分钟的数据量 0.5M*10*60*25 7500MB -> 7GB 多 ◼ …

自学网络安全的三个必经阶段(含路线图)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

blender 快捷键 常见问题

一、快捷键 平移视图&#xff1a;Shift 鼠标中键旋转视图&#xff1a;鼠标中键缩放视图&#xff1a;鼠标滚动框选放大模型&#xff1a;Shift B线框预览和材质预览切换&#xff1a;Shift Z 二、常见问题 问题&#xff1a;导入模型成功&#xff0c;但是场景中看不到。 解…

电路与数字逻辑期末复习重点整理!!

1.带无关项的卡诺图 2.置数法设计N进制电路 计数器&#xff1a;具有记忆输入脉冲个数功能的电路称为计数器。 按照各个触发器状态更新情况的不同可分为&#xff1a; 同步计数器&#xff1a;各触发器受同一时钟脉冲─输入计数脉冲控制&#xff0c;同步更新状态。异步计数器&a…

阿里云centos 7.9 使用宝塔面板部署.netcore 6.0

前言&#xff1a; 我有一个netcore6.0的系统接口和手机端程序的站点程序之前是部署在一台windows测试服务器的IIS站点中&#xff0c; 服务器最近压力太大扛不住了&#xff0c;买了一台centos7.9的阿里云服务器准备进行迁移。具体操作日记如下。 一、安装宝塔面板 这一步涉及…

堡垒机软件详细定义以及部分厂商汇总

随着大家对网络安全的重视&#xff0c;越来越多的企业开始采购堡垒机。堡垒机可以分为硬件堡垒机、软件堡垒机、软硬一体机。今天我们就来聊聊堡垒机软件详细定义以及部分厂商汇总。 堡垒机软件详细定义 堡垒机软件&#xff0c;又称为运维安全审计系统&#xff0c;其主要功能在…

顺序表--数据结构第一关

顺序表 数据结构概念 定义&#xff1a;数据结构是计算机存储、组织数据的⽅式 根据学过C语言的基础上&#xff0c;数组是最简单的数据结构 顺序表的底层就是数组 为什么呢&#xff1f; 例子如下&#xff1a; int arr[100]{1,2,3,4,5}; //修改某一个数据&#xff1a;arr[…

【Docker】docker 替换宿主与容器的映射端口和文件路径

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 docker 替换宿主与容器的映射端口和文件夹 1. 正文 1.1 关闭docker 服务 systemctl stop docker1.2 找到容器的配置文件 cd /var/lib/docker/contain…

掌握 Kubernetes 伸缩:HPA vs VPA 全面解析

前言 在 Kubernetes 中&#xff0c;水平 Pod 自动伸缩 (Horizontal Pod Autoscaler, HPA) 和垂直 Pod 自动伸缩 (Vertical Pod Autoscaler, VPA) 是两种关键的自动伸缩机制。它们在功能和用途上有显著区别&#xff0c;适用于不同的场景。本文将详细解析 HPA 和 VPA 的工作原理…

IAR嵌入式开发解决方案已全面支持矽力杰SA32系列车规MCU

IAR嵌入式开发解决方案已全面支持矽力杰SA32BXX系列车规ASIL-B MCU以及即将推出的SA32DXX系列ASIL-D MCU&#xff0c;共同推动汽车高品质应用的开发 中国上海&#xff0c;2024年6月26日 — 全球领先的嵌入式系统开发软件解决方案供应商IAR与矽力杰半导体&#xff08;以下简称“…

【AI生成】卫星系统海上通信应用及优缺点分析

卫星系统在海上通信中扮演着至关重要的角色&#xff0c;它为船舶、海上平台、搜救行动以及海洋研究等提供了可靠的通信手段。 应用 海上通信应用 1. 船舶通信&#xff1a;卫星通信系统为远洋航行的船舶提供语音、数据和互联网服务&#xff0c;确保船舶与岸上保持联系&#xf…

游戏爱好者将《超级马里奥64》移植到GBA掌机

GBA虽然在当年拥有多款马里奥系列游戏&#xff0c;不过你一定没有想到&#xff0c;N64的《超级马里奥64》也能被移植到这个游戏掌机。近日&#xff0c;一位名为Joshua Barretto的开发者就完成了这一挑战。 大家都知道&#xff0c;《超级马里奥64》于1996年登陆任天堂64主机&am…