Catalina
全类名:org.apache.catalina.startup.Catalina
catalina.load(args)
执行Bootstrap类的load(args)方法,会执行catalina.load(args)方法。
catalina.load(args),代码
/**
* Start a new server instance.
*/
public void load() {
// 省略
// Parse main server.xml,解析server.xml
parseServerXml(true);
Server s = getServer();
if (s == null) {
return;
}
getServer().setCatalina(this);
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
// Stream redirection
initStreams();
// Start the new server 启动server
try {
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(sm.getString("catalina.initError"), e);
}
}
// 省略
}
核心两件事情
1)parseServerXml(true),解析server.xml,生成相应的对象,比如Server、Service、Connector、Engine、Host等等;
解析server.xml,是由Digester完成的。在创建Digester的时候会生成每一个标签节点和类的映射规则,也会生成标签和子标签的关系规则,再根据这些规则,调用Digester的parse方法,生成对应的对象。Server、Service、Connector、Engine等对象都是在这个阶段生成的。
部分代码:
// 获取server.xml
ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()
// 创建 Digester 对象
Digester digester = start ? createStartDigester() : createStopDigester();
InputStream inputStream = resource.getInputStream();
InputSource inputSource = new InputSource(resource.getURI().toURL().toString());
inputSource.setByteStream(inputStream);
// 将当前catalina传入作为起始对象
digester.push(this);
// 开始解析
digester.parse(inputSource);
2)getServer().init(),初始化server,调用Server的init方法。
catalina.start(args)
执行Bootstrap类的start(args)方法,会执行catalina.start(args)方法。
catalina.start(args),简化代码
/**
* Start a new server instance.
*/
public void start() {
// 省略
// Start the new server 启动server
try {
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;
}
// 省略
// Register shutdown hook 注册一个shutdown钩子
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
// 省略
}
if (await) {
// 阻塞线程保证主线程活跃,内部创建一个ServerSocket,监听server.xml配置的shutdown端口8005
await();
stop();
}
}
核心两件事:
1)getServer().start(),启动server,调用server的start方法
2)注册shutdown钩子以及创建ServerSocket监听shutdown指令
shutdown钩子:如果非守护线程都退出或者System.exit方法执行,或者虚拟机被终止了,都会触发这个钩子,从而停止tomcat。
ServerSocket监听:监听server.xml配置的shutdown端口8005,并且接收到的指令是SHUTDOWN,方法不会再阻塞,讲直接调用stop方法。
await和stop方法都是调用的server里的await和stop
server的await简化代码:
// 接收连接时间
socket = serverSocket.accept();
stream = socket.getInputStream();
while (expected > 0) {
ch = stream.read();
command.append((char) ch);
}
boolean match = command.toString().equals(shutdown);
本地启动之后执行:telnet localhost 8005
再输入:SHUTDOWN
则服务将停止。
catalina的stop简化代码:
/**
* Stop an existing server instance.
*/
public void stop() {
// 省略
// Shut down the server
try {
Server s = getServer();
LifecycleState state = s.getState();
if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
&& LifecycleState.DESTROYED.compareTo(state) >= 0) {
// Nothing to do. stop() was already called
} else {
// 停止实例
s.stop();
s.destroy();
}
} catch (LifecycleException e) {
log.error(sm.getString("catalina.stopError"), e);
}
}
catalina.start(args)执行完,服务启动。