tomcat源码 分析 Catalina
通过查看分析启动脚本,发现最终调用的入口是org.apache.catalina.startup包下面的Bootstrap#main
public static void main(String args[]) {
if (daemon == null) {
// Don't set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap();
try {
// 初始化类加载器(这主要是为了要把开发者编写的各种组件应用(WAR 、EAR 等)部署到容器中,并实现组件应用之间的隔离),创建Catalina实例
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);
// 通过反射调用Catalina的load方法,加载server.xml配置、初始化Server
daemon.load(args);
// 通过反射调用Catalina的start方法,开启服务、初始化并开启一系列组件、子容器
daemon.start();
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);
}
}
类org.apache.catalina.startup.Catalina#load分析:
public void load() {
......
//初始化临时目录
initDirs();
// Before digester - it may be needed
//设置额外的系统属性
initNaming();
// Create and execute our Digester
//Digester是apache commons中的一种xml解析器,处理conf/server.xml
//在这个方法里,读取serverl.xml时通过反射实例化了standardServer对象
Digester digester = createStartDigester();
......
try {
inputSource.setByteStream(inputStream);
digester.push(this);
//传入流到digester解析xml拼成对象
digester.parse(inputSource);
} catch (SAXParseException spe) {
log.warn("Catalina.start using " + getConfigFile() + ": " +
spe.getMessage());
return;
} catch (Exception e) {
log.warn("Catalina.start using " + getConfigFile() + ": " , e);
return;
}
......
getServer().setCatalina(this);
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
// Stream redirection
//自定义了System.out.PrintStream,写了一个子类SystemLogHandler继承PrintStream,便于多线程下的日志处理
initStreams();
// Start the new server
try {
//初始化Engine,Executor(用来在connector中管理线程池),Connector,mapperListener(用来监听container的变化的)
getServer().init();
} catch (LifecycleException e) {
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
throw new java.lang.Error(e);
} else {
log.error("Catalina.start", e);
}
}
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
}
}
digester.parse解析xml创建对象的时候相关操作:
1.会绑定HostConfig到StandardHost的lifecycleListeners,然后执行StandardHost.ini时会调用HostConfig.deployApps去查找目录和XML找到Context
类org.apache.catalina.startup.Catalina#start分析:
public void start() {
......
// Start the new server
try {
//启动Engine,Executor,Connector,mapperListener
getServer().start();
} catch (LifecycleException e) {
log.fatal(sm.getString("catalina.serverStartFail"), e);
try {
getServer().destroy();
} catch (LifecycleException e1) {
log.debug("destroy() failed for failed Server ", e1);
}
return;
}
......
//
if (await) {
//调用StandardServer的await方法
//创建socket连接的服务端对象ServerSocket;
//循环等待接收客户端发出的命令,如果接收到的命令与SHUTDOWN匹配(由于使用了equals,所以shutdown命令必须是大写的),那么退出循环等待
//执行shutdown.bat的时候,最终使用java命令执行了org.apache.catalina.startup.Bootstrap类中的main方法,参数是stop,
//通过调用Bootstrap的stopServer方法停止Tomcat,其实质是用反射调用catalinaDaemon(类型是Catalina)的stopServer方法。
//catalina通过创建Digester解析server.xml文件(此处只解析<Server>标签),以构造出Server容器(此时Server容器的子容器没有被实例化);
//从实例化的Server容器获取Server的socket监听端口和地址,然后创建Socket对象连接启动Tomcat时创建的ServerSocket,最后向ServerSocket发送SHUTDOWN命令。
//ServerSocket循环等待接收到SHUTDOWN命令后,最终调用stop方法停止Tomcat。
await();
stop();
}
}
tomcat源码 分析 Catalina的更多相关文章
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- Tomcat源码分析
前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...
- Tomcat源码分析之—具体启动流程分析
从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息 ...
- Tomcat源码分析--转
一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成 ...
- tomcat 源码分析
Tomcat源码分析——Session管理分析(下) Tomcat源码分析——Session管理分析(上) Tomcat源码分析——请求原理分析(下) Tomcat源码分析——请 ...
- Tomcat源码分析——Session管理分析(下)
前言 在<TOMCAT源码分析——SESSION管理分析(上)>一文中我介绍了Session.Session管理器,还以StandardManager为例介绍了Session管理器的初始化 ...
- Tomcat源码分析——Session管理分析(上)
前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对 ...
- Tomcat源码分析——请求原理分析(下)
前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在& ...
- Tomcat源码分析——请求原理分析(中)
前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...
随机推荐
- In Compiler.php line 36: Please provide a valid cache path.
/********************************************************************************* * In Compiler.php ...
- JAVA基础部分复习(一、8中基础类型,以及String相关内容)
以下是关于java中8种基本类型的介绍说明: package cn.review.day01; /** * java基础复习,8种数据类型 * (byte,short,long,int,double, ...
- 修改JAVA代码,需要重启Tomcat的原因
准确的说只有修改方法中的内容才不需要重启,因为tomcat中对于方法的调用是动态的,调用方法的时候,方法的内容才会被加载 新增成员变量,方法,或修改静态方法和静态变量.创建新的类 这些都是需要重启的, ...
- tomcat部署成https协议
1 生成密匙:进入jdk的bin目录后输入: keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keysto ...
- Ubuntu18.10下运行blender2.80bate闪退(问题?)
Ubuntu18.10下直接运行blender2.80bate闪退, 运行blender2.79正常. ================= root@tom-laptop:/# uname -aLin ...
- Project Euler 54
#include<bits/stdc++.h> using namespace std; ]; ]; ; map<char,int> mp; //map<char,cha ...
- Hadoop权威指南
初识Hadoop Hadoop与其它系统比较 数据库的劣势:磁盘寻址性能低发展慢 数据库索引? MapReduce适合一次写入,多次读取的应用,关系型数据库适合持续更新的数据集 Hadoop在处理数据 ...
- 创建新用户,及用新用户名和密码登录--------------DCL
创建用户基本语法: creat user 用户名@"ip地址" identified by "密码" 登录数据库以后:用show databases; 显 ...
- C++中的ravalue学习笔记
一.学习笔记 1. A a = 42; 会先以42为参数构造一个A类对象,然后调用拷贝构造函数来构造a,目前编译器优化掉了拷贝构造函数的调用,测试拷贝构造函数是没有被调用的,但是其权限不能为priva ...
- 使用InternalsVisibleToAttribute给assembly添加“友元assembly”特性遭遇"强签名"
一.如何让Intenal成员暴露给另一个程序集 我们知道Modifier为Internal的类型成员仅限于当前程序集能够访问,但是在某些情况下,我们希望将它们暴露给另一个程序集.比较典型的应用场景包括 ...