21.Spring Bean及Java類的熱部署
簡介
從2.1.1版本開(kāi)始,在URule Pro中提供了Spring Bean及Java類的熱部署功能。利用該功能,打開(kāi)URule Pro控制(zhì)台即可(kě)将需要熱部署的Spring Bean及相關Java類文件實時(shí)部署到正在運行(xíng)的服務器(qì)中。 對于采用客戶端服務器(qì)模式運行(xíng)的URule Pro應用,隻需要在服務端部署好需要的Spring Bean及相關Java類文件,客戶端會(huì)自動獲取這些(xiē)已部署的Spring Bean及相關Java類文件信息,并對其進行(xíng)執加載。
有(yǒu)了這個(gè)功能,URule Pro中無論是用戶自定義的動作(zuò)庫還(hái)是內(nèi)置動作(zuò)庫相關的Spring Bean及Java類,都可(kě)以在服務器(qì)運行(xíng)情況下,實時(shí)動态部署。
部署方式
打開(kāi)URule Pro控制(zhì)台,點擊左側項目列表上(shàng)方按鈕,即可(kě)打開(kāi)動态部署Jar文件的配置頁面,如下圖所示:
在上(shàng)面的部署頁面中,可(kě)以點擊“添加”按鈕添加一個(gè)新的部署項,接下來(lái)點擊具體(tǐ)部署項“操作(zuò)”列中的“編輯”按鈕,即可(kě)在彈出的窗口中添加這個(gè)部署項中涉及到的Jar文件信息,如下圖所示:
在這個(gè)彈出的窗口中,可(kě)以把所有(yǒu)相關的Jar文件通(tōng)過窗口裏選擇文件按鈕上(shàng)傳到知識庫中,完成之後點擊頁面工具欄上(shàng)“部署”,即可(kě)将所有(yǒu)部署項中上(shàng)傳的Jar文件動态部署到當前項目中;如果當前項目被當前URule Server使用,同時(shí)又在各個(gè)項目裏配置了URule的客戶端地址, 那(nà)麽在Server上(shàng)部署完成後,系統會(huì)提示我們要不要将這些(xiē)動态的Jar文件推送到URule客戶端,如果選擇是,那(nà)麽這些(xiē)客戶端立即接收到這些(xiē)Jar文件并動态加載,如下圖所示:
在URule Server的規則項目裏配置客戶端地址,可(kě)以參見客戶端服務器(qì)配置介紹,這裏不再贅述。
Spring配置文件及Jar文件要求
從部署方式上(shàng)了解到,我們隻需要将需要熱部署的Jar包上(shàng)傳到系統即可(kě),如果其中要加載Spring Bean,那(nà)麽還(hái)需要定義好Spring的xml配置文件放在Jar包中一并上(shàng)傳,下面來(lái)舉例說明(míng)Spring配置文件及Jar文件打包方式。
假如我們需要部署下面這個(gè)Java類文件,內(nèi)容如下:
package test;
/**
* @author Jacky.gao
* @since 2019年1月11日
*/
public class BusinessTest {
public String hello(String name) {
System.out.println(new OtherBusiness().getENV());
return "Hello, "+name;
}
}
從上(shàng)面的代碼中可(kě)以看出,這裏的hello方法引用了OtherBusiness類中的getENV方法,OtherBusiness類源碼如下:
package test;
/**
* @author Jacky.gao
* @since 2019年1月11日
*/
public class OtherBusiness {
public String getENV() {
return "環境 is OK...";
}
}
可(kě)以看到getENV方法非常簡單,隻是返回一個(gè)字符串而已,對于BusinessTest類,我們希望它成為(wèi)一個(gè)标準的Spring Bean,所以還(hái)要添加一個(gè)Spring的xml配置文件,內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<bean id="dybean" class="test.BusinessTest"></bean>
</beans>
在上(shàng)面這段xml配置中,test.BusinessTest類被配置成為(wèi)一個(gè)标準的Spring Bean,Bean的ID為(wèi)dybean。到這裏Java類的編寫及Spring Bean的xml配置工作(zuò)就完成了,接下來(lái)就需要将它們打包Jar并上(shàng)傳到URule中實際熱部署。
為(wèi)了演示Java類引用多(duō)個(gè)不同Jar包中其它類庫的情形,這裏我們把BusinessTest類和(hé)OtherBusiness類打成兩個(gè)Jar文件,分别是main.jar和(hé)slave.jar,至于Spring Bean的xml配置文件放在兩個(gè)Jar文件中任何一個(gè)中都可(kě)以,隻是xml的名稱必須是urule-spring-context.xml, 且這個(gè)名為(wèi)urule-spring-context.xml的Spring配置文件必須放在Jar文件的根下,這裏我們把這個(gè)urule-spring-context.xml文件打包在main.jar文件當中。
打包好的main.jar文件結構如下圖所示:
打包好的slave.jar文件結構如下圖所示:
上(shàng)面的兩個(gè)Jar文件中,BusinessTest類和(hé)OtherBusiness類都位于test這個(gè)package下,所以截圖中隻看到test這個(gè)package。 對于URule Pro來(lái)說,每個(gè)Jar文件中都可(kě)以包含一個(gè)名為(wèi)urule-spring-context.xml的Spring的xml配置文件,如果包含每個(gè)文件中的Spring配置文件都會(huì)被解析并加載; 當然也可(kě)以都不包含,這樣熱部署時(shí)引擎隻會(huì)加載Jar包中的類。
配置
當我們點擊“态部署Jar文件的配置頁面”上(shàng)的部署按鈕時(shí),系統會(huì)嘗試取到知識庫裏所有(yǒu)已上(shàng)傳的Jar文件,然後通(tōng)過System.getProperty("java.io.tmpdir")取到當前JVM應用的臨時(shí)目錄,同時(shí)在其下創建名為(wèi)urule-jars的目錄, 最後取當前系統日期作(zuò)為(wèi)Jar文件的最終存儲目錄。
每次點擊“部署”按鈕時(shí),系統都會(huì)嘗試删除原來(lái)的由系統日期生(shēng)成的子目錄,再根據當前日期重新創建子目錄,再把所有(yǒu)的Jar文件放在這個(gè)目錄下。
在臨時(shí)目錄中生(shēng)成好所有(yǒu)的已上(shàng)傳的Jar文件後,接下來(lái)系統會(huì)嘗試加載這個(gè)目錄下的所有(yǒu)Jar文件,如果這些(xiē)Jar文件根下包含名為(wèi)urule-spring-context.xml的Spring配置文件,系統也會(huì)将這個(gè)文件加載到Spring上(shàng)下文中。 在實際使用時(shí),如果運行(xíng)URule Pro的應用采用集群部署,并且集群實例運行(xíng)在同一個(gè)JDK下,這樣多(duō)個(gè)實例運行(xíng)時(shí)通(tōng)過System.getProperty("java.io.tmpdir")取到當前JVM應用采用的臨時(shí)目錄可(kě)能是同一個(gè)目錄,不同的實例操作(zuò)同一個(gè)目錄可(kě)能會(huì)存在問題, 為(wèi)解決這種因集群而導緻的問題,URule Pro允許為(wèi)每個(gè)實例設置一個(gè)名為(wèi)urule.instance.id的JVM參數(shù),要保證每個(gè)實例下該參數(shù)值不同, URule Pro在啓動時(shí)就會(huì)嘗試采用這個(gè)JVM參數(shù)值作(zuò)為(wèi)通(tōng)過System.getProperty("java.io.tmpdir")取到當前臨時(shí)目錄下的子目錄名稱,這樣每個(gè)實例隻會(huì)在這個(gè)子目錄下進行(xíng)創建存儲Jar文件的目錄,通(tōng)過這種方式就可(kě)以避免在一台物理(lǐ)機器(qì)上(shàng)搭建多(duō)集群實例 而産生(shēng)的問題。
實際使用中,如果我們不想讓引擎通(tōng)過System.getProperty("java.io.tmpdir")這種方式,取到的臨時(shí)目錄來(lái)作(zuò)為(wèi)動态Jar文件的存儲父目錄,那(nà)麽可(kě)以在Spring的Properties文件中添加一個(gè)名為(wèi)urule.dynamicJarsPath的屬性來(lái)手工指定一個(gè)用于存儲動态Jar文件的 父目錄,需要注意的是通(tōng)過urule.dynamicJarsPath屬性指定的目錄一定要存在,否則啓動時(shí)會(huì)産生(shēng)錯誤。
對于采用客戶端服務器(qì)模式運行(xíng)的應用來(lái)說,如果客戶端是一個(gè)Java Web應用,那(nà)麽隻需要按照客戶端服務器(qì)配置中介紹的在客戶端中配置好接收服務端推送過來(lái)的知識庫的Servlet即可(kě),這樣服務端動态Jar部署時(shí)會(huì)提示 是否推送到客戶端,如果選是,那(nà)麽這些(xiē)動态Jar文件會(huì)直接推送到目标客戶端,客戶端收到後也會(huì)按照上(shàng)述方式加載這些(xiē)Jar文件及其中可(kě)能存在的名為(wèi)urule-spring-context.xml的Spring配置文件。
和(hé)知識包的客戶端一樣,客戶端也可(kě)以主動檢查服務端是否存在動态Jar文件,檢查方式也是在客戶端上(shàng)配置“urule.resporityServerUrl”屬性值,所以從2.1.1版本開(kāi)始,客戶端中配置好“urule.resporityServerUrl”屬性值後,客戶端應用除了會(huì)利用這個(gè)URL到服務端下載規則包, 還(hái)會(huì)在啓動時(shí)利用這個(gè)URL檢查服務端是否存在動态加載的Jar文件,如果有(yǒu)則下載到客戶端并加載;這時(shí)服務端的“urule/dynamic/checkLatestJarsDir”和(hé)“urule/dynamic/loadDynamicJars”這兩個(gè)URL要保證匿名可(kě)訪問,否則客戶端啓動時(shí)會(huì)産生(shēng)錯誤。
如果客戶端是一個(gè)标準的Java應用,而非一個(gè)Java Web應用,對于這種類型的應用來(lái)說,為(wèi)了可(kě)以取到服務端生(shēng)成的動态Jar文件,我們可(kě)以在客戶端Spring的Properties文件中添加一個(gè)名為(wèi)urule.dynamicJarsRemoteLoadInterval的屬性 來(lái)決定客戶端每隔多(duō)久利用客戶端上(shàng)配置的urule.resporityServerUrl屬性值到服務端檢查有(yǒu)沒有(yǒu)新的動态Jar産生(shēng),如果有(yǒu)則從服務端取回并加載。
urule.dynamicJarsRemoteLoadInterval的屬性值單位為(wèi)分鍾,如果我們設置其值為(wèi)5,那(nà)就表示每隔5分鍾到服務端檢查是否生(shēng)成新的動态Jar文件,如果不設置則表示客戶端不會(huì)定期檢查服務端是否有(yǒu)新的動态Jar包産生(shēng)。