1、Tomcat源码入口

生命周期统一管理接口:LifeCycle

实现LifeCycle接口的类:(idea快捷键:Ctrl+h)

多个组件共同实现LifeCycle接口

Tomcat启动入口分析:

(1)根据不同的操作系统,找到启动脚本,startup.bat/startup.sh,我用的是windows操作系统,用的是startup.bat

startup.bat脚本最后执行函数,执行一个EXECUTABLE变量代表的函数(通过startup.bat去调用catalina.bat脚本),并向函数中传入start参数

(2)catalina.bat脚本中搜索传入的参数"start"

可以看到要去执行dostart函数,最后找到tomcat是由org.apache.catalina.startup.Bootstrap.main()启动的

CATALINA_BASE:         D:\Tomcat\apache-tomcat-8.5.9
CATALINA_HOME: D:\Tomcat\apache-tomcat-8.5.9
Command line argument: -Djava.util.logging.config.file=D:\Tomcat\apache-tomcat-8.5.9\conf\logging.properties
Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
Command line argument: -Dcatalina.base=D:\Tomcat\apache-tomcat-8.5.9
Command line argument: -Dcatalina.home=D:\Tomcat\apache-tomcat-8.5.9
Command line argument: -Djava.io.tmpdir=D:\Tomcat\apache-tomcat-8.5.9\temp

(3)启动类BootStrap,加载初始化以及启动

 public static void main(String args[]) {

        synchronized (daemonLock) {
if (daemon == null) {
// Don't set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init();//初始化
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;//对象赋值
} else {
// When running as a service the call to stop will be on a new
// thread so make sure the correct class loader is used to
// prevent a range of class not found exceptions.
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
} try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
} if (command.equals("startd")) {
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);//加载初始化,一级一级初始化(对象的实例),connector组件endpoint(socket通信端口bind,尚未accept)
daemon.start();//启动,一级一级启动(开始accept接收请求)
if (null == daemon.getServer()) {
System.exit(1);
}
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);
if (null == daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
// Unwrap the Exception for clearer error reporting
if (t instanceof InvocationTargetException &&
t.getCause() != null) {
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
}
}

2、Tomcat初始化

daemon.load(args);//加载初始化,一级一级初始化(对象的实例),connector组件endpoint(socket通信端口bind,尚未accept)
通过load方法通过反射调用catalina.load()方法
catalina.load()方法中调用digester.parse(inputSource)去解析server.xml文件
通过得到的server对象调用init()方法去初始化
init()方法实现LifecycleBase接口的init()方法,LifecycleBase接口的init()方法去调用LifecycleBase.initInternal()方法,而LifecycleBase.initInternal()方法是一个抽象方法,所以具体实现都是在子类中
//使用了模板方法设计模式,在父类中规定执行的步骤,而其中的某些步骤的实现都是在子类中实现
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
} try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
      //init关键之处,实现子类是standardServer类中
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}

standardServer.initInternal()子类中递归调用StandardService.init()方法,对servlet容器和连接器组件进行初始化,后续组件一级一级循环调用,一级一级进行初始化,逻辑相同

 for (int i = 0; i < services.length; i++) {
services[i].init();
}

3、Tomcat启动

启动流程和初始化相似

4、Servlet请求分析

servlet请求——>找到处理servlet实例——>servlet.service()

connect组件接收servlet请求,并传递到servlet容器中——>Engine引擎根据url找到处理servlet的实例

5、Servlet请求处理步骤

请求入口类:NioEndpoint类

NioEndpoint.Poller(),检查是否有可以被处理的socket请求

NioEndpoint.startAcceptorThreads(),用来接收请求的线程

Tomcat学习小记(二)的更多相关文章

  1. Tomcat 学习笔记二

    学习一 java.bean.PropertyChangeListener用来监听bean类的属性值改变.当改变时同时执行对应事件.而且是线程安全的.tomcat用此reload的Boolean值改变是 ...

  2. Tomcat学习之二:tomcat安装、配置及目录文件说明

    我们看到tomcat目录/bin文件夹里有个tomcat6w.exe,顾名思义就是tomcat以window方式显示控制台.第1次点击打开它时候,可能会提示:tomcat指定的服务未安装,此时我们可以 ...

  3. Tomcat学习笔记(二)

    Servlet浅析 javax.servlet.Servlet是一个接口,所有的Servlet必须实现接口里面的方法. 该接口在tomcat/bin中的servlet-api.jar包中. Servl ...

  4. Tomcat学习小记(一)

    1.Tomcat概述 Tomcat 服务器是一个开源的轻量级Web应用服务器,擅长处理动态资源,在中小型系统和并发量小的场合下被普遍使用,是开发和调试Servlet.JSP 程序的首选. Tomcat ...

  5. Tomcat剖析(二):一个简单的Servlet服务器

    Tomcat剖析(二):一个简单的Servlet服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三) ...

  6. Gcd&Exgcd算法学习小记

    Preface 对于许多数论问题,都需要涉及到Gcd,求解Gcd,常常使用欧几里得算法,以前也只是背下来,没有真正了解并证明过. 对于许多求解问题,可以列出贝祖方程:ax+by=Gcd(a,b),用E ...

  7. Shell 学习(二)

    目录 Shell 学习(二) 1 设置环境变量 1.1 基本语法 1.2 实践 2 位置参数变量 2.1 介绍 2.2 基本语法 2.3 位置参数变量应用实例 3 预定义变量 3.1 基本介绍 3.2 ...

  8. crawler4j 学习(二)

    crawler4j 学习(二) 实现控制器类以制定抓取的种子(seed).中间数据存储的文件夹.并发线程的数目: public class Controller { public static voi ...

  9. mongodb入门学习小记

    Mongodb 简单入门(个人学习小记) 1.安装并注册成服务:(示例) E:\DevTools\mongodb3.2.6\bin>mongod.exe --bind_ip 127.0.0.1 ...

随机推荐

  1. 区块链入门到实战(26)之以太坊(Ethereum) – 挖矿

    以太坊(Ethereum)与其他公共区块链一样,使用工作量证明机制确保区块链网络正常运行. 矿工进行工作量证明计算,即挖矿,来选择区块,写入区块链,确认交易. 交易过程如下图所示: 从技术角度来看,以 ...

  2. 都2020年了,还再问GET和POST的区别?【深度好文】

    最近看了一些同学的面经,发现无论什么技术岗位,还是会问到 get 和 post 的区别,而搜索出来的答案并不能让我们装得一手好逼,那就让我们从 HTTP 报文的角度来撸一波,从而搞明白他们的区别. 一 ...

  3. checkbox手动样式改变

    .image_input_checkbox{ width:18px; height:18px; display: inline-block; vertical-align: middle; -webk ...

  4. 【Gin-API系列】守护进程和平滑重启(八)

    生产环境的API服务我们都会部署在Linux服务器上,为了不受终端状态的影响,启动服务的时候会让服务在后台运行.那么如何让服务在后台运行呢,目前有2种常见的方法. 1.nohub 运行 表示忽略SIG ...

  5. 兼容H5页面的js

    (function (doc, win) { let docEl = doc.documentElement; let resizeEvt = 'orientationchange' in windo ...

  6. 在Linux命令行里与其他用户通信

    大家好,我是良许 在 Linux 命令行里向其他用户发送信息很简单,很多命令都可以做到这点,麻烦的是你需要从众多命令中挑选一个合适的命令来使用.因此,我挑选了四种常用的 Linux 用户通信命令分享给 ...

  7. 难道主键除了自增就是GUID?支持k8s等分布式场景下的id生成器了解下

    背景 主键(Primary Key),用于唯一标识表中的每一条数据.所以,一个合格的主键的最基本要求应该是唯一性. 那怎么保证唯一呢?相信绝大部分开发者在刚入行的时候选择的都是数据库的自增id,因为这 ...

  8. html基础:css样式2

    1.字体边框基本设置 <!--border边框:solid实线,red红色,1px粗--> <!--font-weight: bolder字体加粗 font-size:字体大小--& ...

  9. 说说ERP软件的系统设计--开源软件诞生8

    赤龙ERP系统设计篇--第8篇 用日志记录"开源软件"的诞生 赤龙 ERP 开源地址: 点亮星标,感谢支持,与开发者交流 kzca2000 码云:https://gitee.com ...

  10. 内置函数:循环调用函数map和filter

    1.map:循环调用函数,前面一定一定要加list,要不然不会被调用 map的格式:list(map(函数名,循环体)) #这里的函数只能写函数名,不要加() list(map(os.mkdir,[' ...