共计 9501 个字符,预计需要花费 24 分钟才能阅读完成。
Tomcat 有多个容器组成,而 Container 也就是容器与 Connecter 连接器是 Tomcat 最核心的两个模块,Connecter 连接器接收客户端的请求,并根据客户端的请求传递给 Container 处理并作出相应。
Tomcat 中有多个层次的容器对象:Engine、Host、Context、Wrapper,这些容器是有层级关系的。
- Engine:代表整个 Tomcat 的 Servlet 引擎,可以包含一个或多个子容器
- Host:表示一个虚拟主机,包含多个 Context
- Context:表示一个 ServletContext,包含一个或多个 Wrappers 容器
- Wrappers:表示一个独立的 Servlet 定义,可以是多个 servlet 或一个 servlet 实例
所有的容器都继承 ContainerBase 抽象类,ContainerBase 抽象类实现 Container 接口,Container 继承 Lifecycle 接口用于实现对容器的生命周期的统一管理。
Container 接口定义了静态字段来表示添加或移除子容器时的事件类型(如下图):
通过下面图片我们看下 ContainerBase 的类结构,由于篇幅有限方法过多这里就不列出接口、类的字段与方法了:
ContainerBase 类图
Tomcat 所有容器类图如下(省略了字段、方法):
容器类图
这节就先分析到这里,下面我们在详细分析 Tomcat 中的每个容器。
更多 Tomcat 相关教程见以下内容:
CentOS 6.6 下安装配置 Tomcat 环境 http://www.linuxidc.com/Linux/2015-08/122234.htm
RedHat Linux 5.5 安装 JDK+Tomcat 并部署 Java 项目 http://www.linuxidc.com/Linux/2015-02/113528.htm
Tomcat 权威指南(第二版)(中英高清 PDF 版 + 带书签) http://www.linuxidc.com/Linux/2015-02/113062.htm
Tomcat 安全配置与性能优化 http://www.linuxidc.com/Linux/2015-02/113060.htm
Linux 下使用 Xshell 查看 Tomcat 实时日志中文乱码解决方案 http://www.linuxidc.com/Linux/2015-01/112395.htm
CentOS 64-bit 下安装 JDK 和 Tomcat 并设置 Tomcat 开机启动操作步骤 http://www.linuxidc.com/Linux/2015-01/111485.htm
CentOS 6.5 下安装 Tomcat http://www.linuxidc.com/Linux/2015-01/111415.htm
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2016-03/129505p2.htm
Tomcat 由多个组件组成,那么 Tomcat 是怎么对他们的生命周期进行管理的么,这里将从 Tomcat 源码去分析其生命周期的实现;
Bootstrape 类为 Tomcat 的入口,所有的组件够通过实现 Lifecycle 接口来管理生命周期,Tomcat 启动的时候只需调用 Server 容器的 start(),然后父容器依序启动他所包含的子容器,关闭也是如此。
通过阅读源码可知一个 Server 里包含一个或多个 Service,一个 Service 里包含一个 Container,一个或多个 Connector、Container 又包含了 Engine、Host、Context、Wrapper 四个容器;
Tomcat 的组件启动顺序为:
StandardServer.start()——》StandardServer.startInternal() ——》StandardService().start()——StandardService.startInternal() ——>》StandardEngine().start() ——》StandardEngine.startInternal()—》StandardEngine 中启动其他组件,组件关闭也是如此;
现在我们通过 Demo 简单模拟 Tomcat 的启动
模拟 Demo UML 类图
模拟 Demo 时序图
主要代码段如下:
Catalina 类:
package co.solinx.Pattern.Observer;
/**
* Created by LX on 2014/11/26.
*/
public class Catalina {public static void main(String[] args) {
//Tomcat 为多个组件组成的 server 为最外围最大的一个
StandardServer server = new StandardServer();
// 为 server 添加监听器
server.addLifecycleListener(new ContextConfig());
// 添加一个 service
StandardService service = new StandardService();
server.AddService(service);
// 为 service 添加监听器
service.addLifecycleListener(new ContextConfig());
// 添加一个 engine
StandardEngine standardEngine = new StandardEngine();
// 为 engine 添加监听器
standardEngine.addLifecycleListener(new EngineConfig());
StandardHost standardHost = new StandardHost("localhost");
// StandardHost testHost = new StandardHost("test");
// standardHost.addLifecycleListener(new EngineConfig());
standardEngine.addChild("localhost", standardHost);
// standardEngine.addChild("test", testHost);
// 往 service 添加 engine 容器
service.setContainer(standardEngine);
try {server.start();
} catch (LifecycleException e) {e.printStackTrace();
}
}
}
StandardServer 类
package co.solinx.Pattern.Observer;
/**
* Created by LX on 2014/11/26.
*/
public class StandardServer extends LifecycleBase implements Context {Service services[] = new Service[0];
@Override
protected void startInternal() throws LifecycleException {for (int i = 0; i < services.length; i++) {services[i].start();}
System.out.println("StandardServer start");
}
public void AddService(Service service) {Service result[] = new Service[services.length + 1];
System.arraycopy(services, 0, result, 0, services.length);
result[services.length] = service;
services = result;
}
}
StandardService 类:
package co.solinx.Pattern.Observer;
/**
* Created by LX on 2014/11/26.
*/
public class StandardService extends LifecycleBase implements Service, Context {
protected ContainerBase container = null;
@Override
protected void startInternal() throws LifecycleException {container.start();
System.out.println("StandardService start");
}
public void setContainer(ContainerBase container) {this.container = container;}
}
StandardEngine 类:
package co.solinx.Pattern.Observer;
/**
* Created by LX on 2014/11/26.
*/
public class StandardEngine extends ContainerBase {
@Override
protected void startInternal() throws LifecycleException {super.startInternal();
System.out.println("StandardEngine start");
}
protected void addChild(String key, Container container) {super.addChild(key, container);
}
}
LifecycleSupport 类:
package co.solinx.Pattern.Observer;
/**
* Created by LX on 2014/11/26.
* 代理了具体监听者
*/
public class LifecycleSupport {public LifecycleSupport(Lifecycle lifecycle) {super();
this.lifecycle = lifecycle;
}
private Lifecycle lifecycle = null;
private LifecycleListener listeners[] = new LifecycleListener[0];
private final Object listenersLock = new Object(); // Lock object for changes to listeners
public void addLifecycleListener(LifecycleListener listener) {synchronized (listenersLock) {LifecycleListener results[] =
new LifecycleListener[listeners.length + 1];
for (int i = 0; i < listeners.length; i++)
results[i] = listeners[i];
results[listeners.length] = listener;
listeners = results;
}
}
public LifecycleListener[] findLifecycleListeners() {return listeners;}
public void fireLifecycleEvent(String type, Object data) {LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = listeners;
for (int i = 0; i < interested.length; i++)
interested[i].lifecycleEvent(event);
}
public void removeLifecycleListener(LifecycleListener listener) {synchronized (listenersLock) {
int n = -1;
for (int i = 0; i < listeners.length; i++) {if (listeners[i] == listener) {
n = i;
break;
}
}
if (n < 0)
return;
LifecycleListener results[] =
new LifecycleListener[listeners.length - 1];
int j = 0;
for (int i = 0; i < listeners.length; i++) {if (i != n)
results[j++] = listeners[i];
}
listeners = results;
}
}
}
模拟程序运行结果:
Tomcat 有多个容器组成,而 Container 也就是容器与 Connecter 连接器是 Tomcat 最核心的两个模块,Connecter 连接器接收客户端的请求,并根据客户端的请求传递给 Container 处理并作出相应。
Tomcat 中有多个层次的容器对象:Engine、Host、Context、Wrapper,这些容器是有层级关系的。
- Engine:代表整个 Tomcat 的 Servlet 引擎,可以包含一个或多个子容器
- Host:表示一个虚拟主机,包含多个 Context
- Context:表示一个 ServletContext,包含一个或多个 Wrappers 容器
- Wrappers:表示一个独立的 Servlet 定义,可以是多个 servlet 或一个 servlet 实例
所有的容器都继承 ContainerBase 抽象类,ContainerBase 抽象类实现 Container 接口,Container 继承 Lifecycle 接口用于实现对容器的生命周期的统一管理。
Container 接口定义了静态字段来表示添加或移除子容器时的事件类型(如下图):
通过下面图片我们看下 ContainerBase 的类结构,由于篇幅有限方法过多这里就不列出接口、类的字段与方法了:
ContainerBase 类图
Tomcat 所有容器类图如下(省略了字段、方法):
容器类图
这节就先分析到这里,下面我们在详细分析 Tomcat 中的每个容器。
更多 Tomcat 相关教程见以下内容:
CentOS 6.6 下安装配置 Tomcat 环境 http://www.linuxidc.com/Linux/2015-08/122234.htm
RedHat Linux 5.5 安装 JDK+Tomcat 并部署 Java 项目 http://www.linuxidc.com/Linux/2015-02/113528.htm
Tomcat 权威指南(第二版)(中英高清 PDF 版 + 带书签) http://www.linuxidc.com/Linux/2015-02/113062.htm
Tomcat 安全配置与性能优化 http://www.linuxidc.com/Linux/2015-02/113060.htm
Linux 下使用 Xshell 查看 Tomcat 实时日志中文乱码解决方案 http://www.linuxidc.com/Linux/2015-01/112395.htm
CentOS 64-bit 下安装 JDK 和 Tomcat 并设置 Tomcat 开机启动操作步骤 http://www.linuxidc.com/Linux/2015-01/111485.htm
CentOS 6.5 下安装 Tomcat http://www.linuxidc.com/Linux/2015-01/111415.htm
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2016-03/129505p2.htm
从 Tomcat 启动调用栈可知,Bootstrap 类的 main 方法为整个 Tomcat 的入口,在 init 初始化 Bootstrap 类的时候为设置 Catalina 的工作路径也就是 Catalina_HOME 信息、Catalina.base 信息,在 initClassLoaders 方法中初始化类加载器,然后通过反射初始化 org.apache.catalina.startup.Catalina 作为 catalina 守护进程;
一、load
Bootstrap 中 load 流程:
- 反射调用 Catalina 的 load 方法。
- 调用 Catalina 的 initDirs()、initNaming()初始化 catalinaHome、catalina.useNaming 等信息。
- 创建 Digester 对象,调用 createStartDigester 创建与配置 Digester 信息,载入 Server.xml 配置文件,使用 Digester 解析 Server.xml 文件,并根据 Server 文件的配置信息创建 Server、Service、Engine、Host、Valve、Realm、Connector、Listener、Resource 等对象。
- 设置当前 Catalina 为 StandardServer 的 Catalina 对象,调用 initStreams。
- 调用 StandardServer 的 init 方法初始化 Server。
调用 Bootstrap 的 load 方法中用反射调用 Catalina 的 load,在 Catalina 中初始化 initDirs()路径信息,调用 createStartDigester 创建与配置 Digester 信息,载入 Server.xml 配置文件,使用 Digester 解析 Server.xml 文件,并根据 Server 文件的配置信息创建 Server、Service、Engine、Host、Valve、Realm、Connector、Listener、Resource 等对象,及对象的关联关系(Digester 的相关知识这里就不介绍了)。由于在 Digester 解析 Server.xml 的时候已经创建 Server 对象,所以这里也将 server 的 init 方法初始化 Server 对象,至此 Bootstrap 执行完成,准确的说是 Catalina 的 load 载入完成。
二、start
接着将调用 Bootstrap 的 start 方法启动容器,在 start 方法中也是通过反射调用 Catalina 的 start 方法,如下图:
然后在 Catalina 中调用 StandardServer 对象的 start 方法启动 server,在 start 方法中就会像我们在 Tomcat 源码分析之—组件启动实现分析那节中分析的一样,通过 Tomcat 的生命周期管理观察者模式实现对 Service、Connector、Engine、Host、Context、Wrapper、Pipeline 的启动,这里就不重复在讲解了;
三、注册关闭钩子(ShutdownHook)
1 if (shutdownHook == null) {2 shutdownHook = new CatalinaShutdownHook();
3 }
4 Runtime.getRuntime().addShutdownHook(shutdownHook);
四、调用 await()与 stop(),等候关闭请求与 stop 容器
调用 Catalina 的 await 实际上就调用 StandardServer 的 await 如上图,等候 <Server port=”8006″ shutdown=”SHUTDOWN”> 在 Server 8006 端口上的 SHUTDOWN 关闭 Tomcat 请求。
接收到 SHUTDOWN 请求后调用 StandardServer 的 stop 方法与 destroy 方法如下图:
生命周期管理观察者模式实现对 Service、Connector、Engine、Host、Context、Wrapper、Pipeline 的关闭与释放资源
五、总结
Tomcat 的启动与关闭流程到此就结束了,整个流程还是比较清晰的,只要清除 Tomcat 的启动流程也自然就懂得了 Tomcat 的关闭流程,Tomcat 中使用了观察者模式对 Tomcat 的生命周期进行了管理,了解 LifecycleBase、Lifecycle、LifecycleSupport 等相关类也就了解了整个流程,整个流程的时序图如下:
Tomcat 启动与关闭时序图
Tomcat 的详细介绍:请点这里
Tomcat 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-03/129505.htm