Tomcat源码解析(四):tomcat核心组件初始化和启动
来源:互联网 发布:大型企业网络设计方案 编辑:程序博客网 时间:2024/06/06 02:33
Tomcat在接收到用户请求时,将会通过以上组件的协作来给最终用户产生响应。首先是最外层的Server和Service来提供整个运行环境的基础设施,而Connector通过指定的协议和接口来监听用户的请求,在对请求进行必要的处理和解析后将请求的内容传递给对应的容器,经过容器一层层的处理后,生成最终的响应信息,返回给客户端。
Tomcat在提供监听服务前,具体做了什么工作?比如Server和Service以及容器是何时创建?webapps下的项目war包何时加载?同时web.xml文件解析规则?
Tomcat的初始化和启动流程主要围绕核心接口展开,比如Server、Service、Connector、Container、Engine、Host、Context、Wrapper、LifeCycle等等。
startup.bat和catalina.bat脚本
Tomcat启动可以通过startup.bat和catalina.bat脚本执行启动,前者无需参数,默认使用start参数启动Tomcat,后者则需要手动配置参数。
就像所有的Java程序都会有main()方法作为入口,Tomcat也是如此,上面两脚本最终会执行调用Bootstracp类的main()方法作为入口,而Tomcat的核心启动类是Catalina,其会解析server.xml文件并保存Server的引用。而Bootstracp作为适配器,提供多种方式适配Cataline,使Cataline启动提供多种方式。
下面看下Bootstracp的main()方法,主要工作:
1、初始化相关类加载器
2、通过反射方式创建Cataline实例
3、反射调用Cataline实例方法,设置父类加载器
4、调用Cataline实例的process方法
public static void main(String args[]) { // Construct the class loaders we will need ClassLoader commonLoader = null; ClassLoader catalinaLoader = null; ClassLoader sharedLoader = null; // Load our startup class and call its process() method // 反射方式创建Catalina实例 Class startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance(); // 反射方式设置其父类加载器 String methodName = "setParentClassLoader"; Class paramTypes[] = new Class[1]; paramTypes[0] = Class.forName("java.lang.ClassLoader"); Object paramValues[] = new Object[1]; paramValues[0] = sharedLoader; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); // 调用Catalina实例的process方法 methodName = "process"; paramTypes = new Class[1]; paramTypes[0] = args.getClass(); paramValues = new Object[1]; paramValues[0] = args; method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues);}下面进去Catalina实例,首先看下Catalina类的主要成员属性:
// 当前Server配置文件位置 protected String configFile = "conf/server.xml"; // server引用 protected Server server = null; // 是否启动 protected boolean starting = false; // 是否关闭 protected boolean stopping = false;接下来进入Catalina实例的process()方法
public void process(String args[]) { // 设置目录 setCatalinaHome(); setCatalinaBase(); try { if (arguments(args)) // 执行 execute(); } catch (Exception e) { e.printStackTrace(System.out); } }
其把工作传递给execute()方法,而execute()根据是启动命令则传递给start()方法
start()方法主要工作:
1、创建Digester实例,用于解析config/server.xml配置文件信息
2、读取config/server.xml配置文件,并根据Digester规则进行相应解析(创建所有组件,包含各个web应用)
3、执行Server的初始化initialize()方法,初始化Server所管理所有Service服务
4、执行Server的启动start()方法,启动Server所管理的所有Service服务(层层启动所有连接器和容器)
protected void start() { // 创建Digester实例 Digester digester = createStartDigester(); // 获取conf/server.xml配置文件信息 File file = configFile(); // 当前Catalina入栈,用于设置server引用 digester.push(this); // 解析conf/server.xml文件信息 digester.parse(is); Thread shutdownHook = new CatalinaShutdownHook(); // 初始化和启动server if (server instanceof Lifecycle) { server.initialize(); ((Lifecycle) server).start(); // 主线程阻塞等待关闭命令 server.await(); } // 关闭server if (server instanceof Lifecycle) { ((Lifecycle) server).stop(); }}其中调用Server的initialize()方法在前面已经详细分析过,主要就是循环初始化每个Service服务
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(); } }而Server的start()方法也是同样道理,依次启动每个Service服务
public void start() throws LifecycleException { // Validate and update our current component state 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); }
依次启动每个Service服务,而Service服务会依次启动所管理的每个连接器和容器。
总结Tomcat的初始化和启动过程步骤如下:
1、初始化相关类加载器commonLoader、catalinaLoader、sharedLoader;
2、反射机制创建Catalina实例,调用其setParentClassLoader(sharedLoader);
3、反射机制调用Catalina的process()方法;
4、设置基本目录,catalinaHome、catalinaBase;
5、创建Digester实例,用于解析config/server.xml配置文件信息;
6、读取config/server.xml配置文件,并根据Digester规则进行相应解析(创建所有组件,包含各个web应用);
7、执行Server的初始化initialize()方法,初始化Server所管理所有Service服务;
8、执行Server的启动start()方法,启动Server所管理的所有Service服务(层层启动所有连接器和容器);
总结Tomcat初始化和启动流程的时序图如下:
- Tomcat源码解析(四):tomcat核心组件初始化和启动
- Tomcat源码解析(五):Connector连接器的初始化和启动流程
- Tomcat源码阅读之初始化Server组件
- Tomcat源码阅读之初始化连接器组件
- Tomcat源码解读系列(二)——Tomcat的核心组成和启动过程
- Tomcat源码解读系列——Tomcat的核心组成和启动过程
- Tomcat源码解读系列(二)——Tomcat的核心组成和启动过程
- tomcat 解析(五)-Tomcat的核心组成和启动过程
- Tomcat源码解析(十):启动和关闭
- 深入理解 Tomcat(六)源码剖析Tomcat 启动过程----生命周期和容器组件
- Tomcat源码解析(三):service服务组件
- tomcat源码(四) Container启动
- tomcat原理解析(四):启动处理
- Tomcat源码解析(四):session管理
- Tomcat 启动过程源码解析(一)
- Tomcat启动解析web.xml源码分析
- Tomcat关闭过程(Tomcat源码解析四)
- Tomcat关闭过程(Tomcat源码解析四)
- "此证书的签发者无效",系统认证证书(AppleWWDRCA.cer)过期或删除
- Android判断asset中是否存在某个文件
- webapp开发技巧
- 链表的游标实现
- easyui textBox控件,监听事件不好使的解决办法
- Tomcat源码解析(四):tomcat核心组件初始化和启动
- MAT分析
- XMPP的简单了解及使用(2)
- 记录一下在Android使用Json解析字符串
- 由SpringMVC中的Controller注解@RequestMapping引发的思考
- 美女程序员如何面对男友出轨
- 【Android】android开发之splash闪屏页的四种实现方式,启动页的实现教程。
- jenkins导入SVN项目?
- block 跳转