趣操作,Tomcat如何实现一键式启停?

【9.Tomcat底层剖析与性能优化】1.3.1一键式启停:LifeCycle 接口 Tomcat通过LifeCycle接口实现组件生命周期统一管理,采用模板方法、观察者和组合模式三大设计模式。核心类LifecycleBase通过抽象方法实现通用逻辑与具体实现的分离,支持状态转换和事件监听机制。父组件递归调用子组件的启停方法,实现一键式操作。这种设计体现关注点分离、开闭原则等思想,既简化操作又保证可靠性,典型类包括Lifecycle接口、LifecycleBase基类及LifecycleListener监听器。 阅读详情

最新互联网大厂面试真题、Java程序员面试策略(面试前的准备、面试中的技巧)请移步GitHub


首先我们通过一张简化的类图来回顾一下,从图上你可以看到各种组件的层次关系,图中的虚线表示一个请求在 Tomcat 中流转的过程。

上面这张图描述了组件之间的静态关系,如果想让一个系统能够对外提供服务,我们需要创建、组装并启动这些组件;在服务停止的时候,我们还需要释放资源,销毁这些组件,因此这是一个动态的过程。也就是说,Tomcat 需要动态地管理这些组件的生命周期。

在我们实际的工作中,如果你需要设计一个比较大的系统或者框架时,你同样也需要考虑这几个问题:如何统一管理组件的创建、初始化、启动、停止和销毁?如何做到代码逻辑清晰?如何方便地添加或者删除组件?如何做到组件启动和停止不遗漏、不重复?

今天我们就来解决上面的问题,在这之前,先来看看组件之间的关系。如果你仔细分析过这些组件,可以发现它们具有两层关系。

  • 第一层关系是组件有大有小,大组件管理小组件,比如 Server 管理 Service,Service 又管理连接器和容器。
  • 第二层关系是组件有外有内,外层组件控制内层组件,比如连接器是外层组件,负责对外交流,外层组件调用内层组件完成业务功能。也就是说,请求的处理过程是由外层组件来驱动的。

这两层关系决定了系统在创建组件时应该遵循一定的顺序。

  • 第一个原则是先创建子组件,再创建父组件,子组件需要被“注入”到父组件中。
  • 第二个原则是先创建内层组件,再创建外层组件,内层组建需要被“注入”到外层组件。

因此,最直观的做法就是将图上所有的组件按照先小后大、先内后外的顺序创建出来,然后组装在一起。不知道你注意到没有,这个思路其实很有问题!因为这样不仅会造成代码逻辑混乱和组件遗漏,而且也不利于后期的功能扩展。

为了解决这个问题,我们希望找到一种通用的、统一的方法来管理组件的生命周期,就像汽车“一键启动”那样的效果。

一键式启停:LifeCycle接口

我在前面说到过,设计就是要找到系统的变化点和不变点。这里的不变点就是每个组件都要经历创建、初始化、启动这几个过程,这些状态以及状态的转化是不变的。而变化点是每个具体组件的初始化方法,也就是启动方法是不一样的。

因此,我们把不变点抽象出来成为一个接口,这个接口跟生命周期有关,叫作 LifeCycle。LifeCycle 接口里应该定义这么几个方法:init()、start()、stop() 和 destroy(),每个具体的组件去实现这些方法。

理所当然,在父组件的 init() 方法里需要创建子组件并调用子组件的 init() 方法。同样,在父组件的 start() 方法里也需要调用子组件的 start() 方法,因此调用者可以无差别的调用各组件的 init() 方法和 start() 方法,这就是组合模式的使用,并且只要调用最顶层组件,也就是 Server 组件的 init() 和 start() 方法,整个 Tomcat 就被启动起来了。下面是LifeCycle 接口的定义。

可扩展性:LifeCycle事件

我们再来考虑另一个问题,那就是系统的可扩展性。因为各个组件 init() 和 start() 方法的具体实现是复杂多变的,比如在 Host 容器的启动方法里需要扫描 webapps 目录下的Web 应用,创建相应的 Context 容器,如果将来需要增加新的逻辑,直接修改 start() 方法?这样会违反开闭原则,那如何解决这个问题呢?开闭原则说的是为了扩展系统的功能,你不能直接修改系统中已有的类,但是你可以定义新的类。

我们注意到,组件的 init() 和 start() 调用是由它的父组件的状态变化触发的,上层组件的初始化会触发子组件的初始化,上层组件的启动会触发子组件的启动,因此我们把组件的生命周期定义成一个个状态,把状态的转变看作是一个事件。而事件是有监听器的,在监听器里可以实现一些逻辑,并且监听器也可以方便的添加和删除,这就是典型的观察者模式。

具体来说就是在 LifeCycle 接口里加入两个方法:添加监听器和删除监听器。除此之外,我们还需要定义一个 Enum 来表示组件有哪些状态,以及处在什么状态会触发什么样的事件。因此 LifeCycle 接口和 LifeCycleState 就定义成了下面这样。

从图上你可以看到,组件的生命周期有 NEW、INITIALIZING、INITIALIZED、STARTING_PREP、STARTING、STARTED 等,而一旦组件到达相应的状态就触发相应的事件,比如 NEW 状态表示组件刚刚被实例化;而当 init() 方法被调用时,状态就变成INITIALIZING 状态,这个时候,就会触发 BEFORE_INIT_EVENT 事件,如果有监听器在监听这个事件,它的方法就会被调用。

重用性:LifeCycleBase抽象基类

有了接口,我们就要用类去实现接口。一般来说实现类不止一个,不同的类在实现接口时往往会有一些相同的逻辑,如果让各个子类都去实现一遍,就会有重复代码。那子类如何重用这部分逻辑呢?其实就是定义一个基类来实现共同的逻辑,然后让各个子类去继承它,就达到了重用的目的。

而基类中往往会定义一些抽象方法,所谓的抽象方法就是说基类不会去实现这些方法,而是调用这些方法来实现骨架逻辑。抽象方法是留给各个子类去实现的,并且子类必须实现,否则无法实例化。

比如宝马和荣威的底盘和骨架其实是一样的,只是发动机和内饰等配套是不一样的。底盘和骨架就是基类,宝马和荣威就是子类。仅仅有底盘和骨架还不是一辆真正意义上的车,只能算是半成品,因此在底盘和骨架上会留出一些安装接口,比如安装发动机的接口、安装座椅的接口,这些就是抽象方法。宝马或者荣威上安装的发动机和座椅是不一样的,也就是具体子类对抽象方法有不同的实现。

回到 LifeCycle 接口,Tomcat 定义一个基类 LifeCycleBase 来实现 LifeCycle 接口,把一些公共的逻辑放到基类中去,比如生命状态的转变与维护、生命事件的触发以及监听器的添加和删除等,而子类就负责实现自己的初始化、启动和停止等方法。为了避免跟基类中的方法同名,我们把具体子类的实现方法改个名字,在后面加上 Internal,叫 initInternal()、startInternal() 等。我们再来看引入了基类 LifeCycleBase 后的类图:

从图上可以看到,LifeCycleBase 实现了 LifeCycle 接口中所有的方法,还定义了相应的抽象方法交给具体子类去实现,这是典型的模板设计模式。

我们还是看一看代码,可以帮你加深理解,下面是 LifeCycleBase 的 init() 方法实现。

@Override
public final synchronized void init() throws LifecycleException {
	//1.状态检查
	if (!state.equals(LifecycleState.NEW)) {
		invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
	}
	try {
		//2.触发INITIALIZING事件的监听器
		setStateInternal(LifecycleState.INITIALIZING, null, false);
		//3.调用具体子类的初始化方法
		initInternal();
		//4.触发INITIALIZED事件的监听器
		setStateInternal(LifecycleState.INITIALIZED, null, false);
	}
	catch (Throwable t) {
		...
	}
}

这个方法逻辑比较清楚,主要完成了四步:

第一步,检查状态的合法性,比如当前状态必须是 NEW 然后才能进行初始化。

第二步,触发 INITIALIZING 事件的监听器:

setStateInternal(LifecycleState.INITIALIZING, null, false);

在这个 setStateInternal 方法里,会调用监听器的业务方法。

第三步,调用具体子类实现的抽象方法 initInternal() 方法。我在前面提到过,为了实现一键式启动,具体组件在实现 initInternal() 方法时,又会调用它的子组件的 init() 方法。

第四步,子组件初始化后,触发 INITIALIZED 事件的监听器,相应监听器的业务方法就会被调用。

setStateInternal(LifecycleState.INITIALIZED, null, false);

总之,LifeCycleBase 调用了抽象方法来实现骨架逻辑。讲到这里, 你可能好奇,LifeCycleBase 负责触发事件,并调用监听器的方法,那是什么时候、谁把监听器注册进来的呢?

分为两种情况:

  • Tomcat 自定义了一些监听器,这些监听器是父组件在创建子组件的过程中注册到子组件的。比如 MemoryLeakTrackingListener 监听器,用来检测 Context 容器中的内存泄漏,这个监听器是 Host 容器在创建 Context 容器时注册到 Context 中的。
  • 我们还可以在 server.xml 中定义自己的监听器,Tomcat 在启动时会解析 server.xml,创建监听器并注册到容器组件。

生周期管理总体类图

通过上面的学习,我相信你对 Tomcat 组件的生命周期的管理有了深入的理解,我们再来看一张总体类图继续加深印象。

这里请你注意,图中的 StandardServer、StandardService 等是 Server 和 Service 组件的具体实现类,它们都继承了 LifeCycleBase。

StandardEngine、StandardHost、StandardContext 和 StandardWrapper 是相应容器组件的具体实现类,因为它们都是容器,所以继承了 ContainerBase 抽象基类,而ContainerBase 实现了 Container 接口,也继承了 LifeCycleBase 类,它们的生命周期管理接口和功能接口是分开的,这也符合设计中接口分离的原则。

小结

Tomcat 为了实现一键式启停以及优雅的生命周期管理,并考虑到了可扩展性和可重用性,将面向对象思想和设计模式发挥到了极致,分别运用了组合模式、观察者模式、骨架抽象类和模板方法。

如果你需要维护一堆具有父子关系的实体,可以考虑使用组合模式。
观察者模式听起来“高大上”,其实就是当一个事件发生后,需要执行一连串更新操作。传统的实现方式是在事件响应代码里直接加更新逻辑,当更新逻辑加多了之后,代码会变得臃

肿,并且这种方式是紧耦合的、侵入式的。而观察者模式实现了低耦合、非侵入式的通知与更新机制。

而模板方法在抽象基类中经常用到,用来实现通用逻辑。

EDK2多平台编译实战:从树莓派到RK3399的UEFI固件构建 本文提供了从树莓派到RK3399的EDK2多平台编译实战指南。详细介绍了UEFI固件构建的环境搭建、交叉编译配置、平台描述文件修改及常见问题排查,帮助开发者掌握为不同ARM架构硬件构建标准化启动固件的核心技能。 阅读详情

相关推荐

AURIX TC397开发板到手第一步:用iLLD库驱动LED流水灯(附完整代码)

本文详细介绍了如何使用英飞凌AURIX TC397开发板和iLLD库实现LED流水灯效果。从开发环境配置到硬件连接,再到完整的代码实现,逐步引导开发者完成项目。文章还提供了优化建议和常见问题解决方案,帮助嵌入式开发新手快速上手。

weixin_30911451的博客 390

tomcat 的启动文件 start.sh shell脚本详解

前些天,花了一些时间整理linux shell编程。看了一些简单的语法后,觉得还是不够深刻。想着,是不是可以直接查看一些开源软件的启动脚本快速提升shell编写能力。 下面来看看tomcat bin目录下的 start.sh 文件到底在做什么呢? 源码解析 #!/bin/sh # Licensed to the Apache Software Foundation (ASF) under one...

ck3207的博客 7401

蓝牙 - 如何在Windows下抓取蓝牙数据

选择Windows Instarller(64-bit),最好不要选择PortableApps版,因为后面需要通过btvs.exe来启动Wireshark,如果是绿色可移植版,会启动失败。在安装完以后,找到btvs.exe文件,位于路径:C:\BTP\v1.14.0\x86下,这个视安装版本不同路径名不同。在第一台机器上启动btvs.exe,第二台机器上手动启动wireshark,并将第一台机器的IP地址作为参数。1,同一机器上,Wireshark安装后,会自动直接启动,如上面使用方式一样。

guoqx的专栏 2万+

Tomcat源码解析——Tomcat的启动流程

在Catalina的load方法中,会找到server.xml文件,然后解析标签并创建出对应的实例对象,最终在调用最顶层的Server组件的init方法,会调用Service组件的初始化,而Service组件的会调用Connector组件的初始化(容器的初始化是懒加载的,即有请求达到时才开始初始化)。在catalina.sh脚本中,前面是环境判断和初始化参数,最终根据传递的start来执行上图的代码,最终会调用Tomcat的Bootstrap启动类的main方法,传递的参数是start。

m0_37914588的博客 4341

samba源码编译安装(版本4.13.0)

这里写目录标题前言编译安装samba下载三个包安装依赖共需要安装samba、gnutls、nettle1、进入解压后的samba目录执行:2、进入解压后的gnutls目录执行3、进入解压后的nettle目录执行3.1 卸载已存在nettle3.2 编译3.3 make3.4 安装4、进入gnutls继续编译4.1 编译4.2 make4.3 安装5、再次进入解压后的samba目录5.1 执行./configure5.2 make5.3 samba安装启动samba 前言 一般来说,安装samba最快的方式应

灵葱的博客 1万+

Windows下Codex CLI binary报错排查与修复完整指南

在Windows开发环境中,命令行工具与图形界面应用的协同工作常常依赖于系统环境变量的正确配置。Codex CLI作为一款基于Node.js的智能编程命令行工具,其可执行文件(binary)的定位机制直接关系到桌面应用的正常启动。当用户执行npm更新或切换Node版本后,Codex CLI二进制文件路径可能发生漂移,从而触发“Unable to locate the Codex CLI binary”的报错。此类问题并非代码或账号异常,而是PATH路径、环境变量刷新及桌面应用缓存共同作用的结果。本文面向Wi

weixin_28718769的博客 305

Tomcat架构组件原理和生命周期LifeCycle

上层容器的初始化会触发子容器的初始化,上层容器的启动会触发子容器的启动。Connector连接器中的Adapter适配器组件将封装好了的ServletRequest对象传递给Service的Engine容器,Engine处理完毕后继续将请求传递给子容器Host,Host继续处理交给子容器Context,如此下去形成了一个。在Tomcat中,容器的概念就是来装载Servlet的一个管理器,Tomcat基于分层架构的思想,设计了4种容器Engine、Host、Context、Wrapper。...

Minor的Java技术博客 467

利用ORCAD/pspice 仿真分析电路的幅度相位谱

利用ORCAD的pspice仿真分析电路的相位谱1.介绍2.搭建电路原理图3.建立仿真文件,进行交流分析4.仿真、查看输出5.总结 1.介绍 orcad配合pspice一直是电路原理图绘制和仿真的主要工具,pspice工具提供了诸如暂态分析、直流分析、交流分析等多个工具。学校主要教的是multisim,对orcad讲得很少,最进要利用orcad对运放构成的电路的频响、相移特性进行分析,发现资料幅度...

qq_40011737的博客 1万+

Tomcat源码篇-生命周期的架构设计

Tomcat生命周期   在上篇文章中我们看到了Tomcat架构中的核心组件,而且各个组件都有各自的作用,各司其职,而且相互之间也有对应的父子关系,那么这些对象的创建,调用,销毁等操作是怎么处理呢?   也就是在Tomcat中的组件的对象生命周期是怎么管理的呢?针对这个问题,在Tomcat中设计了Lifecycle接口来统一管理Tomcat中的核心组件的生命周期,所以本文我们就系统的来介绍下Lifecycle接口的设计 一、LifeCycle接口设计   为了统一管理Tomcat中的核心组件的生命周期,.

波波烤鸭的博客 1972

大数据开发工程师必备面试题与解答

大数据开发岗位一直是互联网行业的热门方向,面试过程中既考察基础知识,也关注实际项目经验和问题解决能力。本文整理了等核心组件相关的高频面试题及参考解答,帮助大家高效准备面试。大数据面试不仅考察基础理论,更看重项目经验与问题解决能力。本文涵盖了等核心知识点及调优思路,希望能帮助你在面试中游刃有余。

X2829352498的博客 302

Windows 11 安装、使用 Git:下载、安装、概念、命令、分支模型

本文详细介绍了在 Windows 11 系统上安装与使用 Git 的完整流程,涵盖从官方或国内镜像下载安装包、关键安装选项配置,到 Git 核心概念(如工作区、暂存区、分支、远程仓库等)的通俗解释。同时梳理了常用命令与五种主流 Git 分支模型(如 Git Flow、GitHub Flow 等),帮助开发者根据项目规模选择合适的工作流,是面向初学者与进阶用户的实用指南。

寒水馨 · 轻量级技术文档 · hanshuixin.org 2389

面试官:既然启动流程不太了解,那你知道Tomcat的生命周期是什么样子的么?

序言Tomcat的生命周期管理的话,我们不能总是从书中获取那些知识,而是结合实践,然后综合书中的内容,进行一层一层的深入分析,这样对自己记忆和理解都能更加的透彻。启动的时候的大家可以随便找一个zip版本的Tomcat,然后直接启动起来,我们来看看是个什么样子的,一月 11, 2021 10:16:24 上午 org.apache.coyote.AbstractProtocol init 信息: I...

十指波课堂的博客 432

1.14、基于NARX神经网络的磁悬浮建模(matlab)

数据准备:首先,需要准备用于训练和测试的磁悬浮系统的输入和输出数据,包括磁力、电流、位置、速度等信息。数据可以被保存在MATLAB的数据文件中,并加载到工作空间中。使用MATLAB的神经网络工具箱,创建一个NARX神经网络。需要定义网络的层次结构、节点数、激活函数等参数。通常,NARX网络包括自回归层和外部输入层。数据预处理:对加载的数据进行预处理,包括去除噪声、归一化处理等操作,以确保数据质量和网络训练的稳定性。使用MATLAB的训练函数,如trainlm或者trainbr,对NARX神经网络进行训练。

XU157303764的博客 1998

androidstudio在mainactivity实现监听器借口无法抽象_趣操作,Tomcat如何实现一键式启停?

推荐阅读一线大厂为什么面试必问分布式?在一次又一次的失败中,我总结了这份万字的《MySQL性能调优笔记》并发编程详解:十三个工具类,十大设计模式,从理论基础到案例实战首先我们通过一张简化的类图来回顾一下,从图上你可以看到各种组件的层次关系,图中的虚线表示一个请求在 Tomcat 中流转的过程。上面这张图描述了组件之间的静态关系,如果想让一个系统能够对外提供服务,我们需要创建、组装并启动这些组件;在...

weixin_39721853的博客 175

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

你真的了解Tomcat一键启停吗?

Apache Tomcat 的一键启停通常是指在 Linux 或 Windows 操作系统中设置便捷的命令或服务,以便快速启动、停止和重启 Tomcat 服务器。在没有 SpringBoot 内嵌 Tomcat 之前,都是将项目打为 War 包放在 Tomcat 的 webapp 目录下面,然后如果是 Linux 系统,运行命令start.sh、如果是 Windows 系统,运行命令start.bat以后就能启动起来并访问到页面。如果是想要停止运行只需要运行或者。

我是一名热爱编程和分享知识的技术作者,在金融和教育领域有多年的研发管理经验,感谢您访问我的博客,一定会为您带来不一样的收货! 1291

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Tomcat如何启动整个容器的?

Tomcat启动过程前节回顾启动流程图流程详解Lifecycle接口LifecycleEventLifecycleListenerLifecycleSupport监听器的调用下节预告 前节回顾   通过上一节Tomcat架构设计概述我们知道Tomcat容器的整体架构,也都听过Tomcat的一键式启动模式,即当Catalina启动时,其包含的这些组件也会一起启动,同样,当Catalina关闭时,这些...

小呆娃的博客 629

C# 制作Java +Mysql+Tomcat 环境安装程序,一键式安装 (续集Tomcat 配置)

首先我们来了解下,Tomcat 解压版配置需要做哪些事情: 系统要配置好JDK环境变量,Tomcat要能识别到CATALINA_HOME与CATALINA_BASE (就是Tomcat目录添加到环境变量)Tomcat服务的安装 安装方法是命令行切换到Tomcat 的bin目录下,win7 下可按下Shift键 右键鼠标打开命令行,然后输入 service.bat  install  默认的

凯奥的专栏 1189

eclipse的tomcat如何运行自动弹网页_解密:三菱伺服电机遇到一键式干扰如何解决,小白可以进来学习?...

解密:三菱伺服电机遇到一键式干扰如何解决,小白可以进来学习?在施工现场有一台三菱伺服电机遇到一键式干扰如何解决,其实小白也可以进来学习吗?可以的,因为我也是从小白过来的。下面小编为你分享:解密:三菱伺服电机遇到一键式干扰如何解决,小白可以进来学习?请大家花5分钟时间阅读下去,觉得我分享很有价值,记得“收藏”! 故事的开头是这样子的:之前我们工程师使用三菱的伺服电机,电机在空载运行中不定时发生瞬间抖...

weixin_39715538的博客 202

C# 自动部署MYSQL_C# 制作Java +Mysql+Tomcat 环境安装程序,一键式安装 (续集Tomcat 配置)...

usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Configuration.Install;usingSystem.Windows.Forms;usingSystem.IO;usingSystem.Text;usingSystem.D...

weixin_30545945的博客 427

【亲测免费】 Tomcat 7.0~10.0 版本下载仓库:一站式解决你的Tomcat安装需求

Tomcat 7.0~10.0 版本下载仓库:一站式解决你的Tomcat安装需求 【下载地址】Tomcat7.010.0版本下载仓库分享 本仓库提供了一系列Tomcat服务器的安装包和压缩包,涵盖了Tomcat 7.0到10.0的多个版本。无论你是需要zip版的压缩包还是exe版的安装包,这里都能满足你的需求。此外,我们...

gitblog_06509的博客 532

tomcat-maven-plugin

tomcat-maven-plugin , 我们可以使用这个插件把web应用一键式的部署到一个远程的tomcat中。 步骤1 : 修改 tomcat/conf/tomcat-users.xml , 添加tomcat用户,并授予 manage权限 <role rolename="manager-gui"/> <role rolename="manager...

aa292088630的博客 231

【亲测免费】 推荐一键式Linux远程桌面环境搭建工具:OneClickDesktop

推荐一键式Linux远程桌面环境搭建工具:OneClickDesktop 项目简介 OneClickDesktop 是一个令人惊叹的开源脚本,它使得在Linux服务器上安装远程桌面环境变得轻而易举。通过浏览器、VNC或RDP方式即可访问你的桌面,无需额外安装任何客户端软件,尤其是对于Guacamole服务的源码构建,使得这项任务变得更加简洁和高效。 项目技术分析 OneClickDesktop脚本...

gitblog_00083的博客 680
上一篇: 美团 MySQL 数据库巡检系统的设计与应用
下一篇: 程序员职场小技巧:每天工作那么多事,如何安排事务的优先级?
Java_Cappuccino
博客等级 码龄7年 17粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值