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. python练习 - 系统基本信息获取(sys标准库)+ 二维数据表格输出(tabulate库)

    系统基本信息获取 描述 获取系统的递归深度.当前执行文件路径.系统最大UNICODE编码值等3个信息,并打印输出.‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮ ...

  2. 那些jdk中坑你没商量的方法

    前言:jdk作为我们每天必备的调用类库,里面大量提供了基础类供我们使用.可以说离开jdk,我们的java代码寸步难行,jdk带给我们的便利可谓是不胜枚举,但同时这些方法在使用起来也存在一些坑,如果不注 ...

  3. 没想到,Git居然有3种“后悔药”!

    没想到,Git居然有后悔药! 你知道Git版本控制系统中都有哪些"后悔药"吗? 本文通过案例讲解git reset . git revert . git checkout在版本控制 ...

  4. Typescript | Vue3源码系列

    TypeScript 是开源的,TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript.编译出来的 JavaScript 可以运行在任何浏览器上.TypeS ...

  5. Idea使用方式——创建类模板

    问题:创建类或接口时,要添加自定义的默认注释,比如版本,时间等.每个类修改显然不符合程序员的思路,有没有办法通过定义模板来实现? 使用Idea模板 Idea可听过创建类模板来实现. 功能路径:Sett ...

  6. Sql 注入----学习笔记

    先了解下CRLF,CRLF常用在分隔符之间,CR是carriage retum(ASCII 13,\r) LF是Line Feed (ASCII 10,\n), \r\n这两个字符类似于回车是用于换行 ...

  7. web自动化多次打开浏览器嫌烦?打开一次浏览器,pytest有个招

    最近系统前端组件做了更新,我就把之前做的web自动化的代码做了一些修改,顺便优化了下用例,只保留少量的测试用例了,大头还是在接口自动化上.然后发现关于pytest的还有一个点应该比较常用,这里再介绍一 ...

  8. P1164 小A点菜(动态规划背包问题)

    题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过ui ...

  9. 组件给App全局传值vue-bus的使用

    npm安装 npm install vue-bus main.js引入 import VueBus from 'vue-bus' Vue.use(VueBus) 组件 getHouse(e){ thi ...

  10. 柱状图bar

    1.bar的基本设置宽度和圆角 let box1 = document.getElementById('box1') let myEcharts = echarts.init(box1) let op ...