引入:
在Liferay中部署portlet其细节远比向tomcat部署一个web应用那么简单,这文章就来展示下其中的奥秘。
分析:
在这个动作发生后,它会被容器的PortletAutoDeployerListener所捕捉,从而进入到deploy()方法中:
我们可以看到,第43行它其实会去打开这个压缩文件然后比较器结构是否为portlet的xml文件结构,因为满足,所以我们这里执行到第46行,换句话说,我们的部署器(deployer)使用的是 PortletAutoDeployer的实例。
然后会走到第24行,它封装了用PortletAutoDeployer来部署我们的war包的细节:
它会去委托PortletAutoDeployer的deployFile(file,context)方法:
首先,在712行,它会去读写war包中的liferay-plugin-package.xml文件:
吧读来的内容存放在类PluginPackage的实例中:
然后它在第742行来判断当前war包版本(从pluginpackage中读来)是否被目标Liferay容器支持,不支持就抛出一个异常:
这里,显然是支持的,所以跳过这段代码:
然后第751-763行会从pluginPackage中获取推荐的上下文名称,我们这里获得的是logsearchportlet,并且设置给pluginPackage的context属性,最后更新PluginPackage。
接下来会构造部署目录deployDir路径
如上所示,在第765行,如果displayName不为null,则在后面加上.war:
然后来根据服务器类型来对部署目录(deployDir)的名字进行进一步处理:
这里可以看出,如果appServer类型是jboss比较特殊点,但是我们不是jboss,而是tomcat,而且我们unpackWar是true(表明我们要打开这个war包),所以我们的部署目录是在刚才的deployDir的路径基础上去掉最后4个字符,也就是吧.war去掉,所以在第786行之前,现在的deployDir和displayName的值一摸一样,因为加上了.war又去掉了.war了。
所以,我们在786行吧部署的目标目录加载这个部署目录相对路径之前,就得到了部署目录的绝对路径,果然和我们预期是一致的。
接下来,我们就在788行构造一个File对象指向这个部署目录,然后进行文件的生成,复制等操作。
最终会调用deployFile来部署war包到刚才生成的指定部署目录下:
我们来看下它的实现;
撇开一些不重要的东西,我们直接跳到deployFile的第883行,首先可以发现它在$CATALINA_HOME/temp目录下以时间戳为文件名创建了一个临时目录,这个目录用于部署过程的临时目录,然后在887行,吧我们的war文件展开到这个temp目录下:
其中,当调用887行的时候,服务器会打印出一条日志表明这个展开的io操作正在进行
Expanding xxx into xxx/temp/<timestamp>
然后在第888行,我们调用deployDirectory方法来完成具体的部署目录方法,这步骤非常复杂,具体的过程我会在下面一文章中详细介绍,总体来说作用是具体的往部署目录中加入指定的文件,配置等:
最后在893行,吧临时目录删除,然后整个过程就大功告成了。
总结:
我们这里站在1000英尺的高度对于吧war包丢到$CATALINA_HOME/deploy目录后发生的过程进行了非常粗略的分析,大体上说,这其中发生了以下细节:
(1)这个事件会被PortletAutoDeployerListener所捕捉,并且进入其deploy()方法中。
(2)然后为这个war包选择合适的部署器(deployer),它会去打开一个Zip流去读取这个war包并且检查其结构,因为这个war包有portlet.xml文件,所以它会让PortletAutoDeployer充当其部署器。
(3)在PortletAutoDeployer调用deployFile()方法来部署这个war包的时候,它首先会读取lifery-plugin-package.xml文件,并且查看这个war包的版本是否被当前目标Liferay服务器所支持,如果不支持,则停止部署,并且抛出一个异常,如果支持,则继续。
(4)下面,它的主要事情会去创建一个部署目录deployDir字符串,它的起始值是在portlet的displayName后面加上.war. 然后它会去判断服务器类型,然后选择对deployDir的进一步处理,如果是tomcat服务器,并且undeployWar设置为true时候,它会吧后面的.war去除,最后,它吧当前的相对deployDir转为绝对路径的deployDir。
(5)然后它产生一个File对象指向刚才绝对路径的deployDir,并且调用deployFile()方法来部署我们的war包到钢厂在第4步中生成的deployDir部署目录下,这个方法首先会去在$CATALINA_HOME/temp下面以当前的时间戳为文件名创建一个部署过程的临时目录,然后把被部署的war包展开到这个临时目录下, 然后调用deployDirectory方法吧这个临时目录下的文件进行加工,并且丢到最终部署目录deployDir下,最后吧这个临时目录删除。
这里其实最让人感兴趣的其实是最后一步deployDirectory吧临时目录中的内容加工后复制到最终部署目录的细节,因为太复杂, 所以我想用一篇新的文章分析。