前面一节博客说明了Tomcat中Catalina子模块的整体架构,Tomcat中最顶层容器为Server,所有其他组件都被其包含,而Server的关闭启动由Catalina管理,Server的默认实现类为StandardServer,其至少包含一个或者多个Service服务。
1、Server服务器管理组件
Server接口主要方法也是关于对Service服务的管理,以及等待管理端口。
public interface Server {
// shutdown端口管理
public int getPort();
public void setPort(int port);
// 服务组件管理
public void addService(Service service);
public void await();
public Service[] findServices();
public void removeService(Service service);
// 初始化
public void initialize()
throws LifecycleException;
}
StandardServer主要功能:
1、统一管理所有Service服务组件,包含初始化、启动和关闭等操作
2、主线程调用start启动容器后,阻塞等待shutdown关闭命令
由于StandardServer代码较多,不全部贴出,查看其重要属性
// 生命周期工具类,委托管理
private LifecycleSupport lifecycle = new LifecycleSupport(this);
// 等待关闭命令端口
private int port = 8005;
// 相关联的所有Service服务组件
private Service services[] = new Service[0];
// 是否已经启动
private boolean started = false;
// 是否已经初始化
private boolean initialized = false;
Tomcat是通过配置文件server.xml来创建StandardServer实例的,所以StandardServer中许多方法是与server.xml配置文件相关。这里不做介绍。StandardServer中与容器生命周期相关的方法分别是initialize()方法、start()方法、stop()方法、await()方法,接下来主要对这几个方法介绍。
initialize()方法
public void initialize()
throws LifecycleException {
// 防止初始化两次
if (initialized)
throw new LifecycleException (
sm.getString("standardServer.initialize.initialized"));
initialized = true;
// 初始化所有Service组件
for (int i = 0; i < services.length; i++) {
services[i].initialize();
}
}
start()方法
public void start() throws LifecycleException {
// 不能重复启动
if (started)
throw new LifecycleException
(sm.getString("standardServer.start.started"));
// 触发BEFORE_START_EVENT事件,通知相关监听器
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
// 触发START_EVENT事件
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// 启动所有Service服务组件
synchronized (services) {
for (int i = 0; i < services.length; i++) {
// 判断Service是否实现Lifecycle接口
// start方法属于Lifecycle接口
if (services[i] instanceof Lifecycle)
((Lifecycle) services[i]).start();
}
}
// 触发AFTER_START_EVENT事件
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
public void stop() throws LifecycleException {
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("standardServer.stop.notStarted"));
// 触发相关事件,通知监听器
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
// started设置false 注:这里没有设置initialize为false
started = false;
// 依次关闭Service服务组件
for (int i = 0; i < services.length; i++) {
if (services[i] instanceof Lifecycle)
((Lifecycle) services[i]).stop();
}
// 触发相关事件,通知监听器
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
}
await()方法
await()方法创建一个ServerSocket对象监听8005端口,并在while循环中一直等待连接,当指定端口接受到连接accept()才会返回,此时对比接受消息是否是shutdown,是就结束,否则继续监听。
主线程调用await()方法等待,唯一一个用户线程,其余Tomcat线程都是后台线程(Deamon),所以当await接受shutdown指令时,退出while循环,即主线程退出,随即Tomcat关闭。
public void await() {
// 默认端口8005
ServerSocket serverSocket = new ServerSocket(port, 1,
InetAddress.getByName("127.0.0.1"));
// 循环serverSocket监听
while (true) {
// Wait for the next connection
Socket socket = null;
socket = serverSocket.accept();
......读取socket内容
boolean match = command.toString().equals(shutdown);
if (match) {
// 如果是shutdown命令,退出
break;
} else
}
}
public void addService(Service service) {
// 关联当前StandServer
service.setServer(this);
synchronized (services) {
// 更新服务组件services
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;
// 如果Server已经初始化,则初始化当前Service
if (initialized) {
service.initialize();
}
// 如果Server已经启动,则启动当前Service
if (started && (service instanceof Lifecycle)) {
((Lifecycle) service).start();
}
}
}