在 SpringSource dm Server 中部署 GWT 應用程式 - 第 3 部分

工程 | Ben Corrie | 2008 年 12 月 19 日 | ...

簡介

這是描述在 SpringSource dm Server™ 中建置和部署 GWT 應用程式的逐步方法的系列部落格文章的最後一篇。第一篇部落格文章著重於從範例 GWT 應用程式建立簡單 WAR 檔案的流程,第二篇部落格文章將 GWT 依賴項轉換為 OSGi 捆綁包,以便在多個應用程式之間共用。最後這篇部落格文章將使用 Spring Dynamic Modules 進一步模組化我們的 GWT 範例。這應該清楚地展示 OSGi 模組化的優點:在執行期間移除和替換服務的能力、無縫管理多個版本的捆綁包,以及使用 dm Server 進行部署和管理的簡便性。

這是系列文章中唯一實際使用 Spring Framework 的部落格文章。Spring 用於設定 Spring Dynamic Modules,並發布和使用 OSGi 服務。它也示範了將 Spring 管理的 Bean 與 GWT 遠端處理的世界橋接的一種機制。但是,我非常清楚 Spring/GWT 整合本身就是一個重要的主題,因此我在此處特意保持一個簡單的解決方案。

請參閱第 1 部分,以瞭解 GWT StockWatcher 範例的背景以及我使用的軟體。

另請注意,您可以跳過所有這些繁瑣的說明,直接跳到底部的下載摘要。

快速回顧

第 1 部分中,我們從頭開始將 GWT StockWatcher 範例應用程式建置為 Eclipse 專案,然後將程式碼產生到動態 Web 專案中,然後將其部署到 dm Server 中。最後,我們將動態 Web 專案匯出到 WAR 檔案中,並在 STS 外部部署它。

第 2 部分中,我們從 WAR 檔案中移除 GWT 依賴項,並將它們轉換為 OSGi 捆綁包,並將其安裝到 dm Server 的儲存庫中。完成此操作後,我們就能夠部署任意數量的使用 GWT 遠端處理的應用程式,而無需在 WAR 中包含任何 GWT 依賴項。

在最後這部分中,我們將使用 Spring Dynamic Modules 進一步模組化應用程式。您可能會問的一個問題是... 為什麼?這不是一個壞問題 - 沒有人希望為了它而不必要地複雜化他們的程式碼。在決定共用服務方法是否有幫助時,您可以將其歸結為一些簡單的問題

- 我的應用程式的任何部分可能需要被另一個應用程式使用嗎? - 我的應用程式中的不同元件是否會以不同的速率演進? - 我是否有可能需要維護同一元件的多個並行版本? - 我是否希望能夠在應用程式執行時部署對應用程式中元件的變更?

看看我們的 Stockwatcher 應用程式,它目前僅限於一個股票市場。我們知道世界各地有許多不同的市場,因此為了使其更靈活,給予它存取不同市場的能力肯定是有意義的,這就是我們要做的事情 - 將我們的股票市場變成共用服務。一個捆綁包將包含一個共用 API,用於定義市場可以做什麼。其他捆綁包可以是該 API 的實作 - 也許一個用於倫敦,一個用於紐約。然後,我們將能夠部署我們想要的市場、啟動它、停止它、取消部署它並用另一個替換它 - 所有這些都在執行期間完成。

我意識到,將單個 WAR 檔案轉換為共用服務的過程可能比從頭開始以模組化方式設計它更常見,因此這篇部落格文章將進一步建立在我們在第 2 部分中所做的工作之上,而不是重新開始。您可以從第 2 部分在此處下載 Eclipse 專案,並從第 3 部分在此處下載所有工作的完成專案(如果這樣做,您需要定義 GWT_ROOT_INSTALL 類別路徑變數)。希望我在早期部落格文章中關於劃分原始程式碼的一些建議最終會開始變得有意義!

步驟 1:建立 StockService API 捆綁包

為了建立倫敦和紐約 StockWatcherService 實作捆綁包,我們需要它們兩者的通用 API。顯然,模組化通用程式碼是一種良好的實務,但我們需要為 API 建立單獨捆綁包還有一個更重要的原因。如果您想在 dm Server 中執行的應用程式中取消部署捆綁包,您可以安全地移除實作服務的程式碼,但您無法移除剩餘程式碼依賴的任何介面。因此,將我們的服務介面和通用程式碼放入 API 捆綁包中是有意義的,該捆綁包將是其他捆綁包的依賴項。

若要在 Eclipse 中建立簡單的捆綁包專案,請按一下滑鼠右鍵並選取「新增」->「其他」->「SpringSource dm Server」->「捆綁包專案」。這將建立一個骨架MANIFEST.MF供您開始使用。我們無需將其設為 Spring Dynamic Module,因為其唯一目的是提供 API,並且它不會有自己的任何 Bean 實例,因此普通的捆綁包就可以了。

- 將 StockWatcherServiceAPI 指定為專案名稱 - 如果您願意,可以按一下「專案佈局」中的「設定預設...」連結來設定來源目錄。為了保持一致性,我會將其設定為src/main/java- 將捆綁包名稱和符號名稱設定為com.google.gwt.sample.stockwatcher.client.api並將版本保留為1.0.0- 模組類型應為目標執行期應為您的 dm Server 實例。如果您沒有選擇此選項,則需要按一下「新增」並建立一個。 - 您現在可以按一下「完成」,您應該會看到您的新捆綁包專案,其中包含產生的MANIFEST.MF.

接下來要做的是將 API 程式碼移至新專案中。將整個com.google.gwt.sample.stockwatcher.client.api套件從 StockWatcherWar 專案拖放到新的捆綁包專案中。這是用戶端和伺服器共用的所有程式碼。它應該包含StockPriceService介面和StockPriceDelistedException類別。如果成功,幾乎所有內容都應該損壞!

接下來,讓我們思考一下我們需要從新捆綁包中匯出什麼。嗯,在這種情況下很簡單 - 來自一個套件的 API。在MANIFEST.MF編輯器的「執行期」標籤中,將套件新增至「匯出套件」清單並儲存。

現在我們需要思考我們的 API 程式碼需要哪些依賴項,換句話說,為什麼它不再建置了。顯然,我們在第 2 部分中建立的 GWT 捆綁包將是一個好的開始。在「依賴項」標籤中,將 com.google.gwt 捆綁包新增至「匯入捆綁包」清單(如果未列出,則可能不在 dm Server 儲存庫中,這在第 2 部分中說明),然後儲存。這應該修正新專案中的所有建置問題,但其他專案仍應損壞。目前,讓我們忽略這一點,因為還有更多重構工作要做。

此時,StockWatcherServiceAPI 專案應如下所示

MANIFEST.MF應如下所示

步驟 2:建立 StockPriceService 服務捆綁包

在建立包含通用程式碼的 API 捆綁包後,我們可以從中建立多個服務實作,讓我們建立其中一個實作。我們將從倫敦開始。

使用步驟 1 中的說明建立名為「StockWatcherServiceLondon」的新捆綁包專案,並為其指定捆綁包名稱 com.google.gwt.sample.stockwatcher.service.london

因此,讓我們思考一下此捆綁包將需要什麼。它需要程式碼來實作倫敦股票價格服務,以及將該服務匯出到 OSGi 登錄檔作為共用服務的方法。第一部分是一個簡單的重構工作,因為我們已經有一些可以重複使用的服務程式碼。對於第二部分,將捆綁包轉換為 Spring Dynamic Module 將是最簡單的方法,因為它使得使用 Spring Bean 發布和使用 OSGi 服務非常簡單。

首先要做的是。返回並查看StockPriceServiceImpl.java中的服務實作。您會看到StockPriceService程式碼與RemoteServiceServlet綁定在一起。Servlet 需要保留才能使遠端處理工作,但我們需要提取實作程式碼並使用它來建立共用服務。稍後在第 4 部分中,需要調整 Servlet 以使用我們建立的服務。

因此,複製com.google.gwt.sample.stockwatcher.server套件從 StockWatcherWar 專案貼到src/main/javaStockWatcherServiceLondon 的 。您現在應該有一個StockPriceServiceImpl.java的副本,可以進行重構。

刪除extends RemoteServiceServletRemoteServiceServletimport 和SerialVersionUID欄位,因為現在都不需要這些欄位。當您儲存變更時,您會看到我們需要為捆綁包匯入一些依賴項 - 特別是步驟 1 中建立的 API 捆綁包。

編輯MANIFEST.MF以新增com.google.gwt.sample.stockwatcher.client.api的匯入套件。當您儲存時,您應該會在資訊清單中看到一個錯誤,指出無法解析套件。我們做錯了什麼?!問題是,當您在 Eclipse 中的捆綁包專案之間進行匯入和匯出時,您需要告訴工具允許專案共用參考。在 StockWatcherServiceLondon 上按一下滑鼠右鍵,然後選取「屬性」->「專案參考」。勾選 StockWatcherServiceAPI 的方塊,然後按一下「確定」。然後,您需要偽造編輯MANIFEST.MF以擷取變更。您現在應該看到 StockWatcherServiceAPI 列為捆綁包依賴項。讓我澄清一下,一旦捆綁包從 Eclipse 匯出,您就不需要執行這個額外步驟 - 只有當您想要在捆綁包只是專案時在它們之間建立依賴項時才需要。

您仍然應該有一個問題要解決。雖然 com..client.api 捆綁包匯入了 com.google.gwt 捆綁包,但匯入對於該捆綁包是私有的。任何匯入 com..client.api 捆綁包的捆綁包都不會繼承此依賴項 - 它必須明確建立。所以在MANIFEST.MF中,新增一個Import-Bundle用於 com.google.gwt 捆綁包並儲存。如果您仍然在StockPriceServiceImpl.java中看到問題,您可能需要嘗試對其進行偽造編輯,否則您就做錯了什麼。

太棒了!我們現在離建立共用服務只有一半的路程了。這是它目前的樣子

下一步是將 StockPriceServiceLondon 轉換為 OSGi 服務。我們將使用 Spring Dynamic Modules 來做到這一點。Spring Dynamic Module 的原理很簡單 - 您在/META-INF/spring資料夾中提供 Spring 設定檔,並且在部署捆綁包時會為您建立 ApplicationContext。這是一種非常簡單且出色的方式,可將 Spring 管理的 Bean 匯出為 OSGi 服務。

因此,在/spring資料夾中建立/META-INF(在/META-INF上按一下滑鼠右鍵,然後選取「新增」->「資料夾」)。然後在新的/spring資料夾上按一下滑鼠右鍵,然後選取「新增」->「Spring Bean 定義」。您可以隨意呼叫它,但在我的範例中,它稱為serviceLondon-config.xml。輸入名稱,然後按一下「完成」。我們現在需要將StockPriceServiceImpl定義為 Spring Bean,以便在部署捆綁包時建立它的實例。如果您熟悉 Spring,這應該很容易。如果您不熟悉,則需要插入以下 XML

    <bean id="stockPrices"
        class="com.google.gwt.sample.stockwatcher.server.StockPriceServiceImpl"/>

最後,我們需要將此 Bean 匯出為 OSGi 服務。我們可以在同一個設定檔中執行此操作,但最好將 OSGi 依賴項分開。因此,建立另一個名為 osgi-config.xml 的 Spring Bean 定義,這次,在按一下「完成」之前,按一下「下一步」並選取 osgi 命名空間核取方塊。若要將 Bean 匯出為 OSGi 服務,請插入以下 XML

    <osgi:service
        interface="com.google.gwt.sample.stockwatcher.client.api.StockPriceService"
        ref="stockPrices"/>

就是這樣!我們現在有一個捆綁包可以建立共用服務。在我們繼續之前,最好先測試一下,以確保它的行為符合我們的預期。

步驟 3:測試共用服務捆綁包

我將在此處描述兩種測試方法:快速而骯髒的方法和正確記錄的自動化 JUnit 方法。可以說這應該是一篇單獨的部落格文章,但我認為這是一個足夠重要的主題,可以在此處詳細介紹。

快速而骯髒的測試

快速而骯髒的方法是修改另一個 Spring Dynamic Module,它將使用該服務,將其注入到測試類別中,然後僅記錄輸出。這是確保服務運作良好的好方法,但顯然它沒有斷言任何內容,並且無法在測試框架中執行。

因此,我們已經建置了一個 Spring Dynamic Module,因此對於這個新的 TestConsumer 模組,我只會重點說明差異。模組將需要匯入 com.google.gwt.sample.stockwatcher.client.api 捆綁包(或套件),並且它將需要一些 Java 程式碼來呼叫服務用戶端。您將需要在/META-INF/spring資料夾中放入 2 個 Spring 設定檔

一個用於測試 Bean(例如testConsumer-config.xml)

    <bean id="consumer" class="com.ben.consumer.Consumer">
        <constructor-arg ref="priceService"/>
    </bean>

,一個用於<osgi:reference以使用服務(例如osgi-config.xml)

    <osgi:reference id="priceService"
        interface="com.google.gwt.sample.stockwatcher.client.api.StockPriceService"/>

在 Java 程式碼中,只需呼叫service.getPrices(new String{"foo", "bar"}),使用一些任意字串,您應該會收到一個StockPrice物件陣列。如果您想要將輸出記錄到System.err,這會出現在 dm Server 的追蹤目錄中<dm server 安裝目錄>/servicability/trace/<您的測試捆綁包名稱>/trace.log.

若要在 STS 中執行快速而骯髒的測試,您需要啟動 dm Server。然後,將整個 StockWatcherServiceAPI 專案拖放到伺服器上。當專案成功部署時,您應該會收到類似這樣的控制台訊息「com.google.gwt.sample.stockwatcher.client.api」版本「1」的部署已完成。接下來,將整個 StockPriceServiceLondon 專案拖放到伺服器上,並等待部署訊息。如果一切都成功初始化,請將您的測試專案放到伺服器上。

如果您想要讓伺服器每次都乾淨地啟動(清除舊的追蹤輸出等),請新增一個-Dcom.springsource.server.clean=trueVM 引數到啟動設定,您可以透過按兩下伺服器實例、選取「開啟啟動設定」並按一下「引數」標籤來找到該引數。

如果這不起作用,並且您不確定原因,您可以從此處下載我的整個 Eclipse 工作區。

自動化 JUnit OSGi 捆綁包測試

您可以在此處的參考指南中閱讀有關 Spring Dynamic Modules 自動化整合測試支援的資訊。AbstractConfigurableBundleCreator測試類別將啟動 OSGi 框架、載入所有必要的測試捆綁包,然後將您的測試程式碼建置為即時捆綁包並對其進行測試。如果您認為這聽起來可能很複雜,那麼您就說對了。親愛的讀者,我不想讓您感到被虧待,我自己嘗試了這一點,我必須誠實地說,設定它以使所有必要的依賴項都運作起來有點痛苦。因此,這是我一步一步的無痛指南,可讓您啟動並執行。

因此,在開箱即用的情況下,測試預期從本機 Maven 儲存庫取得其所有依賴項。您可以設定測試以使用其他類型的依賴項管理,但為了簡單起見(呵呵!),我正在使用 Maven。首先,我安裝了 m2eclipse,我透過新增http://m2eclipse.sonatype.org/update/作為更新網站(「說明」->「軟體更新」->「可用網站」->「新增網站」)取得了它。建議取消選取選用的 Maven POM 編輯器,否則您會收到一堆未滿足的依賴項警告,並且它將無法安裝。

建立一個名為 StockWatcherServiceTest 的新 Java 專案(以src/main/java作為來源資料夾)。在專案上按一下滑鼠右鍵,然後選取「Maven」->「啟用依賴項管理以 Maven 化專案」。接下來,建立一個新套件(com.ben在我的情況下),並將Spring DM 參考指南中的SimpleOSGiTest程式碼複製到該套件中的測試類別中(請注意,測試框架不允許您使用預設套件)。此測試類別將協助我們健全檢查所有依賴項是否都已正確設定。

您會注意到測試尚未編譯,因為我們還沒有它需要的依賴項。您需要在pom.xml檔案中指定正確的依賴項。為了節省您數小時的握拳和褻瀆,您可以從此處檢視我的pom.xml檔案(包含在完整工作區下載此處中)。一旦您的依賴項運作,請查看您是否可以發現範例程式碼中的錯字、新增 Java 匯入,並且您現在應該有一個可以編譯的測試類別。

嘗試使用「按一下滑鼠右鍵」->「執行身分」->「JUnit 測試」執行測試。如果您收到ClassNotFoundException,那是因為測試在錯誤的位置尋找.class檔案。修正此問題的最簡單方法是覆寫getRootPath()並傳回"file:./target/classes"或您的 .class 檔案正在產生的任何路徑。

希望您現在應該有一個綠色長條圖,至少證明了測試案例啟動了 Equinox 框架,並且能夠成功建立即時捆綁包。現在我們可以為 StockWatcherServiceLondon 捆綁包建立適當的單元測試。

下一步是讓測試依賴項捆綁包正確載入和解析。若要執行此操作,需要將必要的捆綁包安裝在本機 Maven 儲存庫中,並在測試案例的getTestBundlesNames()中指定。

讓我們首先處理 Maven:先前建立的pom.xml檔案應該已下載外部依賴項,但我們需要手動將 com..client.api、com..service.london 和 com.google.gwt 捆綁包新增至 Maven 儲存庫。我透過 Maven 化專案並為每個專案建立pom.xml檔案來對工作區中的捆綁包執行此操作。這裡有幾個陷阱。首先,為了讓 Maven 擷取MANIFEST.MF檔案,您必須在中設定maven-jar-pluginpom.xml,並將其指向檔案的位置。請參閱我的pom.xml 此處。其次,我發現 Spring dm Server 專有的Import-Bundle資訊清單項目不起作用,因此我必須將這兩個專案都變更為使用多個Import-Package項目。完成這些變更後,開啟命令提示字元,變更為專案目錄並輸入mvn install。這將建置外掛程式並將其安裝到本機 Maven 儲存庫中。若要安裝我們在第 2 部分中建置的 gwt 外掛程式,我使用了以下命令列mvn install:install-file -DgroupId=com.google.gwt -DartifactId=com.google.gwt -Dversion=1.5.3 -Dpackaging=maven-plugin -Dfile=<jar 檔案的位置>。此時值得檢查外掛程式是否已正確建置,方法是解壓縮儲存庫中的 jar 並檢查資訊清單是否看起來正常。

一旦所有測試捆綁包都已建置並安裝到儲存庫中,就需要在使用getTestBundlesNames()方法在測試案例中指定它們。語法在參考文件中說明,我指定了 4 個捆綁包:com..client.api、com..service.london、com.google.gwt 和 javax.servlet。

希望此時,您能夠在沒有任何實際斷言的情況下執行測試,但您應該能夠成功地安裝並啟動所有測試捆綁包而不會出現任何問題。如果它不起作用,一個有用的偵錯工具是啟用 Equinox Telnet 控制台,並使用它來檢查預期的匯入和匯出是否都看起來正確。如果您收到ClassNotFoundException,它們可能不正確。啟用控制台的方法是覆寫createPlatform()並呼叫System.setProperty("osgi.console", "9000").

一旦所有捆綁包都已正確解析和啟動,您終於可以編寫一些斷言了!我們需要使用 com..service.london 捆綁包匯出的服務。從上面的快速而骯髒的範例中複製<osgi:reference行到osgi-config.xml檔案中,然後將其新增到測試案例中的getConfigLocations()方法,該方法會傳回設定檔的字串陣列。在這種特殊情況下,我們只是要將其設為普通的 OSGi 捆綁包,而不是 Spring Dynamic Module,因此無需將檔案放入/spring資料夾中。

在整合測試中,Spring 會將所有 Spring 管理的 Bean 自動注入到測試案例中,其中有適當的 Setter,因此新增setStockPriceService(StockPriceService s)方法會將 OSGi 服務注入到測試類別中。一旦您取得服務的參考,您就可以開始對其進行斷言... 終於!

現在,我意識到這是對最終是一個簡單概念的非常冗長的描述。坦白說,了解設定的最佳方法是查看我的 Eclipse 工作區此處。我詳細描述了它,因為看到一個運作正常的範例是一回事,而了解如何達到目的的過程和陷阱完全是另一回事。但是,一旦設定完成,這就是一種非常強大的方式,可以自動化方式整合測試捆綁包服務。

步驟 4:使用共用服務

在步驟 2 中,我們建立了一個 API 捆綁包和一個共用服務捆綁包。我們現在需要重構我們的其他專案以使用這些捆綁包,無論是在編譯時還是在執行期間。在步驟 2 的結尾,您會損壞 StockWatcherWar 和 StockWatcher 專案中的某些依賴項。讓我們首先修正這些問題。

從 StockWatcher 開始,它已損壞,因為我們從它所依賴的 WAR 專案中移除了 API。變更其建置時依賴項,使其參考 StockWatcherServiceAPI 專案(「按一下滑鼠右鍵」->「建置路徑」->「設定建置路徑」->「專案」)。此專案沒有執行期間依賴項,因此這就是需要完成的所有工作。

StockWatcherWar 現在需要進行一些修改才能使用我們在步驟 2 中建立的 OSGi 服務。目前,它仍然包含我們複製到步驟 2 中的服務捆綁包的服務程式碼,因此要完成的一項工作是移除此程式碼,並將其替換為委派給 OSGi 服務的呼叫。但是,這表示我們需要以某種方式將服務捆綁包的參考傳遞到類別中... 這也表示我們實際上需要從某處取得它的實例。讓我們進一步解構它。

好的,因此我們已經知道如何取得服務的參考,因為我們在上面的測試方法中執行了此操作:建立 Spring 設定檔並新增一個<osgi:reference標籤。因此,讓我們從執行此操作開始。在/META-INF中建立新的 Spring Bean 定義(「按一下滑鼠右鍵」->「新增」->「Spring Bean 定義」),隨意呼叫它(例如osgi-config.xml),並確保選取 osgi 命名空間核取方塊以包含結構描述。從步驟 3 新增<osgi:reference範例程式碼,您現在有一個 Spring 設定檔來使用 OSGi 服務。此設定檔是否應放入/spring子目錄以使其成為 Spring Dynamic Module?正確的答案是否定的。我們需要使用它來引導在web.xml中定義的特定風格的 ApplicationContext,因此我們不需要自動為我們建立另一個。

當我們討論這個主題時,請編輯 web.xml 並新增以下幾行

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>com.springsource.server.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/META-INF/*.xml</param-value>
    </context-param>

這將引導 dm Server ApplicationContext 並使用 /META-INF 中的所有 XML 檔案來設定它。

接下來,我們需要找出如何將此 Spring 管理的服務實例傳遞到StockPriceServiceImpl類別,換句話說,一種橋接 Spring 和 Servlet 世界的方法。一種方法是查閱ApplicationContextmaven-jar-pluginServletContext並對其呼叫getBean()。這不是很好,因為它要求我們將 Bean 名稱硬式編碼到服務程式碼中,並依賴依賴項查閱。一種更乾淨的機制是使用 Spring 管理的ServletFilter,將服務實例注入其中,然後使用靜態常數將其傳遞到 Servlet 以進行查閱。這是我在此處實作的內容

此類別應與StockPriceServiceImpl類別一起在 StockWatcherWar 專案中建立。此外,別忘了在FilterChain中委派到doFilter().

如果您仔細遵循說明,則此類別或StockPriceServiceImpl此時都不會編譯,這是由於步驟 1 中的重構。若要修正此問題,您需要將 StockWatcherServiceAPI 新增為 StockWatcherWar 的專案參考(「按一下滑鼠右鍵」->「屬性」->「專案參考」),然後將 com.google.gwt.sample.stockwatcher.client.api 新增至Import-Bundle清單。透過此變更,程式碼現在應該可以編譯了。

既然我們在 Servlet 和 ApplicationContext 之間建立了一個橋樑,我們需要做的就是建立一個ServletFilter的實例,並將服務注入其中。在/META-INF中建立另一個 Spring Bean 定義,隨意呼叫它(例如stockwatcher-config.xml)。將以下設定複製到其中(假設您使用的 OSGi 服務的 Bean 名稱是priceService):

    <bean id="myFilter" class="com.google.gwt.sample.stockwatcher.server.StockPriceServiceFilter">
        <constructor-arg ref="priceService"/>
    </bean>

最後,我們需要一個稱為DelegatingFilterProxy的小魔術。此類別將所有傳入和傳出的 Servlet 請求委派給 Spring 管理的ServletFilter,並在web.xml中定義。將此程式碼複製到您的web.xml中(它假設您的ServletFilter的 Bean 名稱是myFilter)

    <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>myFilter</filter-name>
        <servlet-name>StockService</servlet-name>
    </filter-mapping>

拼圖的碎片終於組合在一起了。您會看到在上面的程式碼中,我們也將DelegatingFilterProxy對應到 StockService Servlet。web.xml設定現在已完成。

現在剩下的就是取得StockPriceServiceImpl程式碼中的服務實例並使用它!

鑑於我們似乎已經考慮到了一切,請嘗試將 WAR 專案部署到 dm Server,方法是遵循步驟 3 中用於快速而骯髒測試的相同說明:將 API 專案放到伺服器上,然後將 London Service 專案放到伺服器上,最後將 StockWatcherWar 專案放到伺服器上。

您應該會看到以下內容

[2008-12-19 17:46:23.504] onnection(4)-192.168.1.5 <SPDE0010I> 「com.google.gwt.sample.stockwatcher.client.api」版本「1」的部署已完成。[2008-12-19 17:46:44.125] onnection(4)-192.168.1.5 <SPDE0010I> 「StockWatcherServiceLondon」版本「1」的部署已完成。[2008-12-19 17:47:03.528] onnection(4)-192.168.1.5 <SPSC1000I> 正在建立 Web 應用程式「/StockWatcherWar」。[2008-12-19 17:47:03.544] async-delivery-thread-1 <SPSC1001I> 正在啟動 Web 應用程式「/StockWatcherWar」。[2008-12-19 17:47:03.676] async-delivery-thread-1 <SPSC1005E> 無法啟動 Web 應用程式「/StockWatcherWar」:請查閱伺服器 trace.log 以取得更多詳細資訊。[2008-12-19 17:47:03.680] async-delivery-thread-1 <SPSC1002I> 正在移除 Web 應用程式「/StockWatcherWar」。[2008-12-19 17:47:03.752] onnection(4)-192.168.1.5 <SPDE0011E> 「com.google.sample.stockwatcher」版本「1」的部署失敗。

部署失敗?在完成所有這些工作之後?天啊!這裡有什麼問題?

查看<dm Server 安裝>/serviceability/trace/com.google.sample.stockwatcher-1/trace.log中的追蹤檔。您應該會看到ClassNotFoundException: org.springframework.web.context.ContextLoaderListener。問題是,現在我們處於明確匯入和匯出的世界中,我們需要明確匯入在 WAR 檔案中為我們提供 Spring 支援的捆綁包,因此請將以下捆綁包新增至Import-Bundle項目:org.springframework.context、org.springframework.core、org.springframework.beans 和 org.springframework.web。它現在應該看起來像這樣

現在再次嘗試部署它。這次,我保證,它應該可以運作。在它運作之前,請勿繼續執行步驟 5。

步驟 5:慶祝

掃蕩迷你吧、泡杯茶、跳舞或揮拳,無論哪種方式適合您的文化和預算。

步驟 6:熱交換不同的服務

現在是時候炫耀 dm Server 的絕活之一了。

首先,讓我們建立另一個我們可以交換的股票市場服務。這與複製/貼上工作沒有太大區別。在 StockWatcherServiceLondon 專案上按一下滑鼠右鍵,選取「複製」,然後選取「貼上」。將複製的專案命名為 StockWatcherServiceNewYork。要編輯的內容如下

- MANIFEST.MF- 將捆綁包名稱和符號名稱從 London 更新為 NewYork。-serviceLondon-config.xml- 重新命名,但無需變更任何內容 -StockPriceServiceImpl.java- 大幅變更價格,以便明顯看出我們正在使用不同的股票市場。我只是在每個價格上增加了 500。道瓊指數加油!

接著進入有趣的部分。如同先前一樣啟動 StockWatcherWar 並使用倫敦股票服務,然後新增幾個股票,這樣你就可以看到它運作了。

接著在伺服器視窗中,於 StockWatcherServiceLondon 項目上按一下滑鼠右鍵,然後選擇「移除」。這會將 StockWatcherServiceLondon 組合從伺服器取消部署。你現在會看到應用程式暫停。對遠端服務的呼叫將會被封鎖,直到 dm Server 輪詢到替換服務。所以我們來提供一個替換服務。選取 StockPriceServiceNewYork 專案並拖曳到伺服器上。等待幾秒鐘,然後... 瞧!應用程式現在正在使用紐約服務 (請注意價格顯著上漲)。

步驟 7:在 STS 之外部署

在 STS 之外部署應用程式很簡單,只需匯出組合即可。方法會根據你是否使用 Maven 以及 Maven 是否自動執行作業而有所不同。除非你只匯出以下項目,否則在 Maven 專案上使用「匯出 -> Jar 檔案」將會失敗:/src目錄。無論你是否使用 Maven,你還需要選取「使用工作區中現有的 manifest」。

組合匯出後,有幾種封裝方式,然後也有幾種部署方式。

在封裝方面,你可以將它們保留為個別的組合,或者你可以將它們全部合併到單一 PAR 檔案中。PAR 檔案看起來像是一個包含組合的組合,並且在這裡 說明 中有描述。使用 PAR 檔案的顯著好處是它會在「範圍」中執行其組合,因此它與在其他應用程式中執行的其他組合完全隔離。但是,如果你將應用程式部署為 PAR,則無法在其中熱抽換個別的組合。

一旦你決定了部署模式,你可以使用管理控制台上傳檔案,或者你可以將它們複製到<dm Server 安裝目錄>/pickup目錄中。第一次執行此操作時,伺服器需要已經在執行中,並且你應該以正確的順序將組合複製到目錄中。dm Server 會記住下次你啟動伺服器時的順序。使用此機制的優點是你可以透過簡單地將個別組合移入和移出此目錄來熱部署或取消部署它們。

下載摘要

我意識到我已經在整個部落格中分散了下載連結,所以我認為應該在這裡總結一下。另外,很抱歉將小檔案壓縮成 zip 檔,但由於安全因素,部落格工具不允許我上傳原始的 XML 或 Java 檔案。祝你玩得開心!
  • 整個第 3 部分的工作區專案,包括兩種測試機制,都可以在這裡下載。

  • 匯出的組合可以從這裡下載。

  • 專案的 PAR 檔案 (包含倫敦市場) 可以從這裡下載。

訂閱 Spring 電子報

隨時掌握 Spring 電子報的最新資訊

訂閱

領先一步

VMware 提供訓練和認證,加速你的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部