引入:
在上文中,我们从宏观上讲解了Liferay部署war包的动作是如何触发监听器并且完成部署过程的,但是其中最核心的一块deployDirectory我们没讲,它的作用是当有了临时目录并且已经把war包的内容展开到该目录之后,是如何对其中内容进行解析,再加工并且最终复制到最终的部署目录deployDir的,我们这里就研究这块内容:
调试分析:
首先,我们看下这个复杂方法的入参:
srcFile参数是我们临时目录,也就是被展开的war文件对应的目录。
mergeDir是一个目录,用于merge的,我们设置为在LIFERAY部署目录($LIFERAY_HOME/deploy)中建一个merge目录,然后以我们的war包名字为子目录,如下:
deployDir不用说了, 也就是在tomcat的webapps目录下我们的应用最终要放置到的目录:
后面3个参数不用说了。
我们开始分析:
首先在第514行调用rewriteFiles去重写临时目录中srcDir中的几个文件:
代码我不贴了,一看就懂,它的目的是对于web.xml, liferay-plugin-package.xml,liferay-display.xml,liferay-portlet.xml,portlet.xml这5个文件进行子元素的缩进,并且缩进量都是一个制表符的距离。所以最终文件都会变成:
这种缩进格式
接着在第516行中调用mergeDirectory(mergeDir,srcFile)方法,.因为我们的mergeDir为空,所以直接这段代码跳过。
接着在第518行调用processPluginPackageProperties(srcFile,displayName,pluginPackage)对于plugin package的properties文件进行处理,因为我们没有liferay-plugin-package.properties,取而代之我们是用xml文件的,所以这段代码也跳过。
接着会在第520行调用copyJars(srcDir,pluginPackage) 方法,
他们会吧$CATALINA_HOME/liferay/com/liferay/portal/deploy/dependencies目录下的多个jar文件
分别复制到我们srcFile指定的portlet临时目录下的WEB-INF/lib目录下。
细心的你一定会问,为什么突然多出来$CATALINA_HOME/liferay/com/liefray/portal/deploy/dependencies目录,为什么会有这么多jar文件?其实我也不知道,我们在最后“精华疑点解答中”会分析,这里姑且假定这个目录已经存在并且由这些jar文件吧。
然后在第521行调用copyProperties(srcFile,pluginPackage)方法。
细节我省去了,它会去吧logging.properties,log4j.properties,service.properties等这些文件从$CATALINA_HOME/temp/liferay/com/liferay/portal/deploy/dependencies目录
复制到我们用srcFile变量指定的portlet临时目录下的WEB-INF/class目录下。
接下来它会在第522行调用copyTlds(srcFile,pluginPackage)方法:
他们会吧aui.tld,liferay-portlet.tld,liferay-portlet-ext.tld,liferay-security.tld,liferay-theme.tld,liferay-ui.tld,liferay-util.tld这些Taglib定义文件都复制到我们用srcFile变量指定的portlet临时目录下的WEB-INF/tld目录下,那么这些原始文件在哪里呢?也许你猜对了,他们还是在$CATALINA_HOME/temp/liferay/com/liferay/portal/deploy/dependencies 目录下:
接下来它会去调用copyXmls(srcFile,displayName,pluginPackage)方法。
首先它会调用super.copyXmls,这个的作用是用来判断服务器类型来确定如何去复制服务器特定的xml文件和web.xml文件到我们用srcFile变量指定的portlet临时目录下的WEB-INF目录下:
因为我们的appServerType是"tomcat",所以它不会复制服务器特定的xml文件,只会复制一个web.xml。
然后因为我们appServerType是'tomcat",所以它会复制context.xml文件到我们用srcFile变量指定的portlet临时目录下的/META-INF目录下。
最后会吧_servlet_context_include.jsp文件复制到我们用srcFile变量指定的portlet临时目录下的/WEB-INF/jsp目录下.
那么这些xml文件是不是还是在$CATALINA_HOME/temp/liferay/com/liferay/portal/deploy/dependencies 目录下呢?回答正确~
接下来它在第524行调用copyPortalDependencies(srcFile) ,因为我们没有定义plugin package的properties文件,所以这行没执行。
接下来它在第530行调用updateWebXml(webXml,srcFile,displayName,pluginPackage)方法对于我们从$CATALINA_HOME/temp/liferay/com/liferay/portal/deploy/dependencies目录下直接复制来的最原始的xml进行更新,对其中内容进行了增删,(关于这一块也十分复杂, 我准备另外用一文章来介绍)
接下来对于/WEB-INF/ext-lib/global和/WEB-INF/ext-lib/portal中的jar包处理,把他们复制到liferay 服务器上的对应目录,因为我们没有,所以跳过。
接下来在第558行,调用updateDeployDirectory(srcFile)对部署目录进行更新。
然后对于jar包进行排除操作了:
首先,它先判断服务器类型,因为我们是tomcat ,所以它会去吧tomcatLibDir中的所有的jar包都放在排除列表中,这个tomcatLibDir是
然后它会去读取刚才conext.xml,如果其中指定了com.liferay.support.tomcat.loader.PortalClassLoader,那么就去掉3个jar包。
然后把**/WEB-INF/web.xml也加在exclude列表中,因为这web.xml总要被改动的,所以我们这个文件不会最终复制到tomcat下的webapps下我们应用的deployDir中。最终我们的exclude列表如下:
然后第674行执行复制动作,它吧我们的$CATALINA_HOME/temp/<时间戳下>的我们的临时的应用信息去除exclude列表中的web.xml和一些jar文件其他全部复制到$CATALINA_HOME/webapps/<项目名>这个最终部署目录下:
最后第678行单独复制web.xml文件,并且overrite设置为true, 表示覆盖原有的。我们从服务器的所有文件时间戳可以看到这一点,如下:
从上面我们可以看到WEB-INF目录下,只有最后一行的web.xml的时间戳比较上次发生了改变,这就表明这个web.xml是单独复制的,实践果然和代码执行相互吻合。
最后第690行吧这个新生成的web.xml的lastModified设置为当前的时间+6秒。
最最后吧我们吧tempDir(也就是我们在$CATALINA_HOME/temp/<时间戳>)这个目录删除,
就一切大功告成了,从deployDirectory()方法返回。
精华疑点解答:
在总结之前,还有一个疑惑没明白,就是我们看部署的很多动作都是要先从$CATALINA_HOME/liferay/com/liefray/portal/deploy/dependencies目录中吧各种文件,(包括properties文件,tld文件,xml文件等)复制到tempDir中,那么这个文件是何时生成的又是为什么包含这么多内容呢?我们现在来专门研究这个问题。
很快就找到了答案,它这些内容从classpath复制到$CATALINA_HOME/temp/liferay 目录下的。
而classpath这些文件,经过仔细查找,发现都来自于$CATALINA_HOME/webapps/ROOT/WEB-INF/lib/portal-impl.jar ,比如说所有用到的tld文件:
总结:
(1)deployDirectory的整体作用是在tomcat的temp目录拥有一个从war包展开的目录结构然后经过一些配置,重组,最后复制到webapps下响应应用的部署目录的过程。
(2)首先它会调用rewriteFiles去重写目录下的几个xml文件,目的是让文件更规范,有缩进的格式。
(3)然后它会读取plugin-package.properties中的属性设定到Properties中。
(4)然后调用copyJars()方法吧CATALINA_HOME/liferay/com/liferay/portal/deploy/dependencies目录下的多个jar文件分别复制到我们srcFile指定的portlet临时目录下的WEB-INF/lib目录下。
(5)然后调用copyProperties吧CATALINA_HOME/liferay/com/liferay/portal/deploy/dependencies
目录下的多个properties文件分别复制到我们srcFile指定的portlet临时目录下的WEB-INF/classes目录下.
(6)然后调用copyTlds吧CATALINA_HOME/liferay/com/liferay/portal/deploy/dependencies
目录下的多个tld文件分别复制到我们srcFile指定的portlet临时目录下的WEB-INF/tld目录下.
(7)然后调用copyXmls方法,先根据服务器类型来决定吧服务器特定的xml文件和web.xml文件复制到我们srcFile指定的portlet临时目录下的WEB-INF目录下,如果是tomcat服务器还要复制context.xml文件到portlet临时目录下的META-INF目录下,然后把_servlet_context_include.jsp复制到portlet临时目录下的WEB-INF/jsp目录下。以上文件都是从CATALINA_HOME/liferay/com/liferay/portal/deploy/dependencies目录中获取的。
(8)然后调用updateWebXml(webXml,srcFile,displayName,pluginPackage)方法对于我们从$CATALINA_HOME/temp/liferay/com/liferay/portal/deploy/dependencies目录下直接复制来的最原始的xml进行更新,对其中内容进行了增删(这个放在以后文章中单独讨论)
(9)接下来对于/WEB-INF/ext-lib/global和/WEB-INF/ext-lib/portal中的jar包处理,把他们复制到liferay 服务器上的对应目录
(10)从第(4)-(8)中的每一步复制,这些资源文件都是来自于CATALINA_HOME/liferay/com/liferay/portal/deploy/dependencies 目录,而这些资源文件最初都是来自$CATALINA_HOME/webapps/ROOT/WEB-INF/lib/portal-impl.jar中,这些资源在Liferay运行后会被加载到classpathResource中。
(11)在最终复制到webapps下的部署目录之前,它必须要先生成一个排除列表,表明在复制时候那些资源要先排除,web.xml总是被排除的, 另外还有一些jar文件,取决于我们的配置。
(12)复制到webapps下部署目录的动作总是分为2部分,一是复制除排除列表中的所有文件目录,二是单独复制web.xml文件,所以每次可以看到web.xml的时间戳总比其他文件晚。
(13)最后复制完会到webapps下我们应用的部署目录下把最新的web.xml的lastModified属性往后面调6秒。