引入:
在上文中,我們從宏觀上講解了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個文件進行子元素的縮進,并且縮進量都是一個制表符的距離。所以最終文件都會變成:
<parent-ele>
? ? ? ?<child-ele>
這種縮進格式
接著在第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秒。