博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
How Tomcat works — 七、tomcat发布webapp
阅读量:6546 次
发布时间:2019-06-24

本文共 4592 字,大约阅读时间需要 15 分钟。

目录

  • 什么叫发布
  • webapp发布方式
  • reload
  • 总结

什么叫发布

发布就是让tomcat知道我们的程序在哪里,并根据我们的配置创建Context,进行初始化、启动,如下:

  • 程序所在的位置
  • 创建Context,添加到Host
  • 初始化(创建解析webxml的digester)
  • 启动(初始化filter、listener、servlet)

webapp发布方式

在tomcat 中发布webapp的方式不同会导致app启动的先后顺序不一样(这里按照启动顺序或者时机不同进行划分):

  1. 在xml中配置,在conf/server.xml中配置(在host标签内部)
  2. 直接将webapp文件夹、war包放在tomcat下面的"webapps"目录,或者在webapps下面新建一个xml(根标签为context,在属性中表明应用程序的位置)

其实两种发布方式只是在启动顺序上稍有不同,启动过程完全一致,先以在server.xml中配置说明

在server.xml进行配置

这情况在我们使用eclipse等工具进行开发发布的时候,eclipse会帮我们在server.xml的Host标签内添加Context,如下:

View Code

在新建server的时候会解析server.xml,同时也会根据我们上面的配置新建StandardContext,而且会将StandardContext作为Host的一个Child(可以在Catalina.createStartDigester方法中查看怎么解析server.xml),在tomcat的启动过程中context是由父容器host启动的

额,看到这张图发现似曾相识,对滴,就是Context的初始化,因为在tomcat中一个context实例就代表一个webapp,所以其实应用程序webapp的发布本身就是context的初始化和启动,再看看context的启动

以上已经完整展示了一个webapp的发布过程,也就是在server.xml的配置的webapp发布过程,接着来看看在webapps目录下的发布过程。

在webapps目录下

在StandardHost的startInternal方法中调用了父类的ContainerBase.startInternal方法,在StandardHost发布完在server.xml中配置的app之后,会调用setState来切换自身的状态,这个时候就会触发listener HostConfig的lifecycleEvent方法

@Overrideprotected synchronized void startInternal() throws LifecycleException {    // Start our subordinate components, if any    if ((loader != null) && (loader instanceof Lifecycle))        ((Lifecycle) loader).start();    logger = null;    getLogger();    if ((manager != null) && (manager instanceof Lifecycle))        ((Lifecycle) manager).start();    if ((cluster != null) && (cluster instanceof Lifecycle))        ((Lifecycle) cluster).start();    Realm realm = getRealmInternal();    if ((realm != null) && (realm instanceof Lifecycle))        ((Lifecycle) realm).start();    if ((resources != null) && (resources instanceof Lifecycle))        ((Lifecycle) resources).start();    // Start our child containers, if any    // 因为在解析server.xml的时候已经新建了Context,这里就可以直接start    Container children[] = findChildren();    List
> results = new ArrayList
>(); for (int i = 0; i < children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); } boolean fail = false; for (Future
result : results) { try { result.get(); } catch (Exception e) { log.error(sm.getString("containerBase.threadedStartFailed"), e); fail = true; } } if (fail) { throw new LifecycleException( sm.getString("containerBase.threadedStartFailed")); } // Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start();   // 调用lifecycleEvent方法,触发StandardHost的start事件,触发监听器HostConfig的start方法,所有在webapps下面的都在start方法中发布 setState(LifecycleState.STARTING); // Start our thread threadStart();}

调用过程如下:

(上图中主要画出了deployWars的调用过程,其他两个deploy方法也类似)

在HostConfig.deployApps方法中主要进行了:

  • 调用deployDescriptors:发布所有使用xml配置的webapp,因为可能有多个xml,所以在该方法内部又调用了deployDescriptor来发布每个xml对应的webapp
  • 调用deployWars:发布所有在webapps目录下的war包,也可能存在多个
  • 调用deployDirectories:发布所有直接部署在webapps目录下的应用程序

前面说过了,发布webapp就是新建一个context对象并初始化、启动,上面三个方法中主要的作用为:

Class
clazz = Class.forName(host.getConfigClass());LifecycleListener listener = (LifecycleListener) clazz.newInstance();context.addLifecycleListener(listener);context.setName(cn.getName());context.setPath(cn.getPath());context.setWebappVersion(cn.getVersion());context.setDocBase(cn.getBaseName() + ".war");host.addChild(context);
  • 构建一个StandardContext
  • 将context添加到host中,在Container.addChildInternal方法中会调用context.start

接下来的步骤就和上面在server.xml配置的webapp启动一致了。

reload

在我们使用tomcat开发web的时候经常会用到“热加载”(热部署)功能,那么原理究竟是什么呢?上面介绍了webapp发布,因为reload功能也是从HostConfig开始的,所以继续介绍reload功能

上面的ContainerBase.startInternal是由StandardEngine.startInternal方法调用的,启动了一个daemon线程定时检测webapp是否发生变化(文件是否被修改),如果被修改了则会重新启动StandardContext。

总结

像tomcat部署和发布,我们天天都在用,可是不知道究竟原理怎么样的,在学习了tomcat源码之后,对这一切都更加明了。知其然,知其所以然。

转载于:https://www.cnblogs.com/sunshine-2015/p/5770556.html

你可能感兴趣的文章
Bzoj1758: [Wc2010]重建计划
查看>>
redis集群部署及踩过的坑
查看>>
j2EE监听器-listener
查看>>
使用pip命令报You are using pip version 9.0.3, however version 18.0 is available pip版本过期.解决方案...
查看>>
(转)LINQ之路
查看>>
volatile和synchronized的区别
查看>>
10.30T2 二分+前缀和(后缀和)
查看>>
vuex视频教程
查看>>
Java 线程 — ThreadLocal
查看>>
安居客爬虫(selenium实现)
查看>>
-----二叉树的遍历-------
查看>>
ACM北大暑期课培训第一天
查看>>
F. Multicolored Markers(数学思维)
查看>>
nodjs html 转 pdf
查看>>
Python字典
查看>>
Android存储方式之SQLite的使用
查看>>
洛谷P1287 盒子与球 数学
查看>>
Bootstrap vs Foundation如何选择靠谱前端框架
查看>>
与、或、异或、取反、左移和右移
查看>>
vue常用的指令
查看>>