領先一步
VMware 提供培訓和認證,助您加速發展。
瞭解更多正如在第 1 部分中提到的,我在這篇部落格中不使用Spring Framework,而是專注於 SpringSource dm Server™ 和 SpringSource Tool Suite 來部署“純粹的” GWT。
請參閱第 1 部分瞭解 GWT StockWatcher 示例的背景以及我使用的軟體。
此處描述的分步方法將基於我們在第 1 部分中完成的工作,而不是從頭開始。我們在第 1 部分中現在要更改的唯一一件事是刪除對以下庫的顯式依賴:gwt-servlet.jar庫。
好訊息是,建立這些依賴項的大部分工作已經有人為您完成了。SpringSource Enterprise Bundle Repository 包含了大多數常用庫的“打包”版本。然而,在撰寫本文時,我們的 GWT 依賴項是一個需要您自己將其轉換為 Bundle 的庫示例。幸運的是,Eclipse 3.4 使這個過程非常簡單。
- 在“專案資源管理器”中右鍵單擊,選擇“新建”->“其他”->“外掛開發”->“從現有 Jar 歸檔檔案建立外掛”。- 點選“新增外部”,然後瀏覽找到gwt-servlet.jar。- 點選“下一步”,並將專案命名為“com.google.gwt”。- 設定外掛版本以反映 GWT 版本,在本例中是 1.5.3。- 選擇“分析庫內容並新增依賴項” - 選擇 Equinox OSGi 框架
點選“完成”,無需切換到外掛開發透檢視。我們只是要直接將我們的 Bundle 再次匯出。
您現在應該會看到生成的MANIFEST.MF檔案,其中定義了 Bundle 的依賴項。您將在“執行時”選項卡中看到該工具已添加了所有com.google.gwt..包作為匯出。您還將在“依賴項”選項卡中看到它已經識別出此 Bundle 需要一些javax.servlet..包以及一個junit包。
我們現在將移除 JUnit 依賴項,因為它在 dm Server 中預設將無法解析。當然,如果我們願意,我們可以向 dm Server 新增一個 JUnit Bundle 來滿足此依賴項,或者,我們可以透過新增以下內容使該依賴項成為可選的:required:=optional。選擇junit.framework包,點選“移除”,然後儲存。
值得指出的是,這是一種將 JAR 檔案轉換為 Bundle 的粗略方法,不能保證在所有情況下都能奏效。一方面,我們可能不想匯出所有包。更重要的是,有一些原始碼級別的陷阱可能在 OSGi 中表現不佳,例如使用Class.forName()。如有疑問,請務必首先檢視 SpringSource Enterprise Bundle Repository,而不是嘗試自己建立。
最後,我們需要將我們的外掛專案匯出為一個 OSGi Bundle。選擇“匯出”->“外掛開發”->“可部署外掛和片段”。選擇一個方便的位置作為輸出目錄。
我們現在應該會在以下路徑看到一個檔案:<export path>/plugins/com.google.gwt_1.5.3.jar。下一步是將檔案重新命名,使其與 dm Server 中其他命名 Bundle 的格式一致:只需將下劃線更改為破折號com.google.gwt-1.5.3.jar。如果不進行此更改,當前版本的 STS 將無法識別 Bundle 版本。如果您想跳過此步驟,可以從此處下載。
最後,將 Bundle 複製到 dm Server 的 Bundle 倉庫中:<dm Server installation root>/repository/bundles/usr。這裡的任何 Bundle 都可以成為 dm Server 中其他 Bundle 的依賴項,但重要的是它在 STS 中也將作為依賴項可見,正如我們在下一步中將看到的。
此時,您可以從工作區中刪除 com.google.gwt 專案,因為它已經完成了它的使命。
下一步是“破壞”我們的應用程式!
右鍵單擊 StockWatcherWar,選擇“屬性”->“Java EE 模組依賴項”,取消選中gwt-server.jar檔案,然後點選“確定”。我們現在已經刪除了 WAR 對 GWT 的顯式依賴,給自己造成了許多新問題,其中大多數是編譯器錯誤。
所以我們需要將我們的動態 Web 專案轉換為一個 dm Server Bundle,以便它可以從我們新建立的 GWT Bundle 中顯式匯入所需的依賴項。為此,右鍵單擊 StockWatcherWar,選擇“Spring Tools”->“新增 OSGi Bundle 專案特性”。您應該注意到該專案現在帶有一個非常重要的“S”符號,並且MANIFEST.MF也改變了字元。
它現在處於破損狀態,因為它看起來不像一個 Bundle 清單。讓我們新增一些合理的預設值(您可以複製貼上以下內容,或使用選項卡中的欄位)。請注意,您也可以在編輯器中使用 ctrl-space 來提示您有效的選項。
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: com.google.sample.stockwatcher Bundle-SymbolicName: com.google.sample.stockwatcher Bundle-Version: 1.0.0 Bundle-Description: Shared Libraries StockWatcher demo
這樣就解決了一個問題,我們的 Bundle 清單現在看起來正常了。然而,我們尚未定義對 GWT Bundle 的依賴,所以我們仍然有一些編譯器錯誤。
選擇“依賴項”選項卡並點選“新增”。在頂部,您應該會看到一個 com.google.gwt Bundle 神奇地出現了。現在,重要的是要明白,此列表中出現的 GWT Bundle 與我們在步驟 1 中建立的外掛專案無關。如果您從工作區中刪除該專案,該 Bundle 仍然會出現在列表中。這是因為 dm Server 安裝被設定為專案的執行時環境,因此工具會在 dm Server 的倉庫中查詢您可能想要匯入的任何 Bundle。如果這一步沒有成功,則說明 GWT Bundle 沒有被複制到正確的位置,或者 WAR 專案的執行時環境沒有設定為 dm Server。請在“屬性”->“目標執行時”中檢查後者。
接下來,選擇 GWT Bundle,點選“確定”,然後儲存清單。您現在應該會看到 GWT Bundle 被新增到一個名為“Bundle Dependencies”的新類路徑元素中。
您現在應該注意到大多數錯誤已經解決,但仍有幾個未解決。這是因為我們的 GWT Bundle 依賴於javax.servletAPI,並且在我們獲得這些類之前,型別層次結構是不完整的。
那麼,為什麼當我們之前只有gwt-servlet.jar在我們的構建路徑中時,沒有遇到這個問題呢?嗯,在我們進行更改之前,我們的 WAR 會拾取其構建路徑上的所有內容,其中包括 dm Server 目標執行時提供的所有 JAR。然而,您可能已經注意到,當我們新增 OSGi Bundle 專案特性時,構建路徑上的 dm Server JAR 檔案消失了。這是因為,透過成為 OSGi Bundle,我們進入了一個不同的依賴關係世界,在這個世界裡,匯入和匯出必須顯式宣告。
宣告我們對javax.servletAPI 的依賴項很簡單,只需匯入另一個 Bundle。您將在列表中看到它,名稱為com.springsource.javax.servlet。新增這兩個 Bundle 後,儲存清單,您現在應該會看到所有錯誤都已解決。太好了!
如果我們現在導航到 MANIFEST.MF 選項卡,我們可以看到我們所有點選操作的效果:清單中有一個綠色的“Import-Bundle”條目。請注意,我們也可以在“Import-Bundle”後面輕鬆使用 ctrl-space,它會建議所有可能的匯入。
如果您想檢視我的專案,可以從此處下載一個壓縮副本。它包括在嵌入式 Tomcat 中以 hosted mode 啟動、在 dm Server 中以 hosted mode 啟動以及啟動 GWT 編譯器的執行時配置。請注意,使用嵌入式 Tomcat 的 hosted mode 可以正常工作,無需修改 Bundle WAR 專案。這是因為javax.servlet從 dm Server 獲得的包不再位於構建路徑中。要使用我的專案,您需要設定GWT_ROOT_INSTALL變數,並且您可能需要選擇您的 dm Server 目標執行時例項,如第 1 部分中所述。
為了好玩,讓我們看看幕後,瞧瞧我們的 Bundle 是如何互動的。
dm Server 啟動時,會通知您其 OSGi 控制檯可以透過 telnet 客戶端訪問:
[2008-10-27 16:48:04.266] main <SPOF0001I> OSGi telnet console available on port 2401.
讓我們開啟一個終端視窗,看看能發現什麼:
> telnet localhost 2401 Trying ::1... Connected to localhost. Escape character is '^]'.
osgi>
您可以透過輸入 help 來獲取 Equinox 控制檯可用的命令列表。還有一篇有用的 DeveloperWorks 文章,您可以在此處閱讀。
輸入ss可以列出所有正在執行的外掛:
osgi> ss
Framework is launched.
id State Bundle . . . . 73 ACTIVE com.google.sample.stockwatcher_1.0.0 74 ACTIVE com.google.gwt_1.5.3
輸入packages 74可以列出 GWT Bundle 中所有匯出的包。它顯示所有匯出的包都被 StockWatcherWar Bundle 匯入。這是我們使用“Import-Bundle”的結果。實際上,我們的 StockWatcherWar 唯一需要的包是com.google.gwt.user.client.rpc和com.google.gwt.user.server.rpc。如果我們願意,我們可以改用“Import-Package”更具選擇性地顯式匯入這些包。這在dm Server 程式設計指南中有所描述。
file:////Users/bcorrie/dmServer-1.0.0/springsource-dm-server-1.0.0.RELEASE/work/com.springsource.server.deployer/Module/StockWatcherWar.war-0/StockWatcherWar.war [73] imports com.google.gwt.i18n.client.constants; version="0.0.0"<file:////Users/bcorrie/dmServer-1.0.0/springsource-dm-server-1.0.0.RELEASE/repository/bundles/usr/com.google.gwt-1.5.3.jar [74]>
然而,GWT 發行版中包含的一個確實使用了簡單遠端處理的示例叫做 DynaTable。我使用這些部落格中描述的相同步驟和原理,將此示例轉換為一個共享庫 WAR 檔案。要了解我是如何做的,您可以下載壓縮後的專案或WAR 檔案檢視。這非常簡單地演示了在 dm Server 中執行多個應用程式的原則,所有這些應用程式都共享我們建立的 GWT Bundle。