久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

使用 WebSphere Application Server V7 Feature Pa...

 埃德溫會(huì)館 2011-05-31

在 OSGi 容器中運(yùn)行 Spring 應(yīng)用程序,然后遷移到一個(gè)基于標(biāo)準(zhǔn)的依賴性注入容器

Valentin Mahrwald , OSGi 應(yīng)用程序開發(fā)工程師, IBM
Tim Ward, OSGi 應(yīng)用程序 JPA 主管, IBM
Zoe Slattery, OSGi 技術(shù)推廣者, IBM

 

簡(jiǎn)介: Spring 和 OSGi 框架是用于應(yīng)用程序開發(fā)的強(qiáng)大工具,,給應(yīng)用程序開發(fā)人員帶來(lái)重大價(jià)值,。隨著 IBM? WebSphere? Application Server V7 Feature Pack for OSGi Applications 的發(fā)布,WebSphere Application Server 現(xiàn)在為 OSGi 應(yīng)用程序和依賴性注入提供可擴(kuò)展的基于標(biāo)準(zhǔn)的運(yùn)行時(shí),。本文描述如何通過(guò)部署基于 Spring 的 Java? EE 應(yīng)用程序到 OSGi 容器來(lái)獲得 OSGi 的基本模塊化優(yōu)勢(shì),,如何將 Spring XML bean 定義遷移到基于標(biāo)準(zhǔn)的 OSGi Blueprint 組件模型來(lái)獲得聲明性 OSGi 服務(wù)的全部好處,并從應(yīng)用程序中消除依賴性注入容器的負(fù)擔(dān),。 本文來(lái)自于 IBM WebSphere Developer Technical Journal 中文版,。

發(fā)布日期: 2011 年 5 月 19 日
級(jí)別: 中級(jí)
原創(chuàng)語(yǔ)言: 英文
建議: 0 (添加評(píng)論)

1 star2 stars3 stars4 stars5 stars 平均分 (共 0 個(gè)評(píng)分 )

簡(jiǎn)介

Spring Framework 及其相關(guān)項(xiàng)目是廣泛使用的一套 Apache licensed 庫(kù),,旨在讓 Java Standard Edition (Java SE) 和 Java Enterprise Edition (Java EE) 環(huán)境更便于開發(fā)人員使用,。Spring 庫(kù)允許提取企業(yè)技術(shù)(比如 Java Transactions API),這樣應(yīng)用程序就寫入了 Spring API,,且可以在 Java SE 或 Java EE 運(yùn)行時(shí)中運(yùn)行,,而無(wú)需更改應(yīng)用程序邏輯。

Spring Framework 的基石之一是 Inversion of Control (IOC) 容器,該容器提供靈活,、功能齊全的機(jī)制來(lái)構(gòu)建 POJOs (Plain Old Java Objects) 和執(zhí)行用于連接這些對(duì)象的依賴關(guān)系圖的依賴性注入,。該構(gòu)造和連接邏輯通常在 XML 中提供,但是還有大量其他配置選項(xiàng),。Spring 等 Dependency Injection 框架的主要價(jià)值在于,,通過(guò)移除從應(yīng)用程序中管理對(duì)象關(guān)系和生命周期的責(zé)任,代碼可以將重點(diǎn)放在直接實(shí)現(xiàn)業(yè)務(wù)邏輯上,。此外,,通過(guò)提供被注入對(duì)象的存根實(shí)現(xiàn)、改進(jìn)測(cè)試覆蓋率和代碼質(zhì)量,,可輕松對(duì)編寫良好的應(yīng)用程序類執(zhí)行單元測(cè)試,。

Spring Framework 還因其 Model View Controller (MVC) Web 框架、聲明性事務(wù)管理支持和 Data Access Object (DAO) 框架而得到大量采用,。這些技術(shù)通常與其他開源技術(shù)(比如 Apache OpenJPA,、JBoss 和 Apache Tomcat)或 IBM WebSphere Application Server 等 Java EE 應(yīng)用程序服務(wù)器結(jié)合使用。經(jīng)結(jié)合后,,這些技術(shù)旨在提高基于 servlet 的 Web 應(yīng)用程序的開發(fā)速度,,簡(jiǎn)化其邏輯并在一個(gè)輕量級(jí)容器中提供企業(yè)級(jí)服務(wù)質(zhì)量。

OSGi Alliance 是負(fù)責(zé) Java 的靈活模塊化技術(shù)規(guī)范的標(biāo)準(zhǔn)組織,。提供一個(gè)能夠并發(fā)運(yùn)行同一代碼的多個(gè)版本的框架,,還有一個(gè)用于表達(dá)外部依賴關(guān)系的強(qiáng)大機(jī)制,以及外部提供的模塊 API,,在 OSGi 中也稱為捆綁包,。OSGi 定義大量接口和合約,對(duì) Java 運(yùn)行時(shí)主要實(shí)現(xiàn)三個(gè)方面的增強(qiáng):

  • OSGi 框架的第一層稱為模塊層,,該層定義以良好封裝的方式共享類定義和資源的方法,。
  • 第二個(gè) OSGi 層是生命周期層,它定義在一個(gè)運(yùn)行的系統(tǒng)中動(dòng)態(tài)添加,、刪除,、啟動(dòng)、停止和修改捆綁包的方法,。這允許以無(wú)序的方式調(diào)出基于 OSGi 的系統(tǒng),,能夠讓捆綁包獨(dú)立于彼此而運(yùn)行。
  • OSGi 框架的第三層是服務(wù)層,。服務(wù)層定義一個(gè)運(yùn)行時(shí)機(jī)制,通過(guò)這種機(jī)制可以松耦合方式動(dòng)態(tài)共享對(duì)象實(shí)現(xiàn),。服務(wù)注冊(cè)表中的服務(wù)可以快速響應(yīng)系統(tǒng)中的變化,,而且捆綁包可以基于運(yùn)行時(shí)中可用的服務(wù)主動(dòng)改變其行為。

雖然很多開發(fā)組織重視從使用 Spring 這樣的框架中獲得的價(jià)值,,他們常常擔(dān)心將應(yīng)用程序容器作為其應(yīng)用程序的一部分加以維護(hù)的負(fù)擔(dān),,而不是將其作為基礎(chǔ)中間件平臺(tái)的一部分予以提供,。這些組織可能也擔(dān)心 Spring 這樣的框架給其所在的每個(gè)應(yīng)用程序帶來(lái)的大量磁盤和內(nèi)存占用。

此外,,有大量開發(fā)組織希望利用 OSGi 提供的強(qiáng)大的成熟模塊化技術(shù),,而且希望利用由 OSGi 服務(wù)注冊(cè)表實(shí)現(xiàn)的動(dòng)態(tài)、靈活的應(yīng)用程序結(jié)構(gòu),。這些組織常常因難以利用 OSGi 和缺乏明確的應(yīng)用程序編程模型而受到阻礙,。

本文描述如何使用 WebSphere Application Server V7 Feature Pack for OSGi Applications 和 JPA 2.0(以下簡(jiǎn)稱 OSGi 功能包)及其 OSGi Blueprint 容器以基于標(biāo)準(zhǔn)的方式獲得使用 Spring 的優(yōu)勢(shì),其中大量繁重工作由 WebSphere Application Server 容器完成,。本文還就運(yùn)行和遷移基于 Spring 的應(yīng)用程序到 OSGi 提供了詳細(xì)指導(dǎo),。(參見 為 WebSphere Application Server 開發(fā)企業(yè) OSGi 應(yīng)用程序 了解有關(guān) OSGi 應(yīng)用程序的更多信息。)

什么是 OSGi Blueprint Service,?

Blueprint Service(通常稱為 Blueprint)是一個(gè)基于 POJO 的 OSGi 組件模型,。它提供一個(gè)依賴性注入容器,允許自動(dòng)管理一個(gè)對(duì)象的生命周期,。Blueprint 與 OSGi 服務(wù)注冊(cè)表相集成,,支持托管的實(shí)例透明地使用或被呈現(xiàn)為 OSGi 服務(wù)。

對(duì)于使用過(guò) Spring Framework 的開發(fā)人員來(lái)說(shuō),,Blueprint 看起來(lái)非常熟悉,。這是因?yàn)?Blueprint 標(biāo)準(zhǔn)是與 SpringSource VMware(Spring 框架背后的公司)協(xié)力開發(fā)的,真正是 Spring Dynamic Modules 項(xiàng)目的一個(gè)標(biāo)準(zhǔn)化版本,。因此,,Blueprint 提供與 Spring 相同的優(yōu)勢(shì)給應(yīng)用程序開發(fā)人員,支持松耦合和靈活配置,。還有很多其他好的理由來(lái)使用 Blueprint(參見 參考資料 中有關(guān) OSGi 最佳實(shí)踐的文章),。

本文中描述的示例將僅利用 Blueprint 容器中的基本功能,即依賴性注入,,將 beans 顯示為服務(wù),,引用來(lái)自 OSGi 服務(wù)注冊(cè)表的服務(wù)。但是還有更多高級(jí)功能,,包括復(fù)雜的對(duì)象構(gòu)造,、容器調(diào)用初始化和析構(gòu)方法、服務(wù)生命周期通知和服務(wù)引用列表,。更多細(xì)節(jié)可在 OSGi Service Platform Enterprise Specification 和 “使用 Blueprint Container 規(guī)范構(gòu)建 OSGi 應(yīng)用程序” 一文中找到,,兩者均在 參考資料 中。

先決條件

本文面向?qū)?OSGi 感興趣且對(duì) Spring Framework 依賴性注入模型以及 Java Persistence API (JPA) 或類似的對(duì)象關(guān)系型映射技術(shù)有基本了解的 Spring 和 Java EE 開發(fā)人員,。您應(yīng)當(dāng)熟悉使用 Apache Ant 構(gòu)建工具和 Java 編程語(yǔ)言,。如果您希望執(zhí)行這里描述的遷移步驟,一個(gè)現(xiàn)代 Java IDE(雖然在技術(shù)上不需要),比如 Eclipse,、Netbeans 或 IntelliJ,,會(huì)很有幫助。

要運(yùn)行本文提供的示例,,您需要安裝通過(guò) OSGi 功能包增強(qiáng)的 WebSphere Application Server V7,。要構(gòu)建樣例,您需要 Apache Ant 版本 1.7.1 或更高版本的一份工作副本,。


回頁(yè)首

Blether 應(yīng)用程序簡(jiǎn)介

本文主要圍繞如何將一個(gè)基本的社交網(wǎng)絡(luò)應(yīng)用程序從基于 Spring 的 Java EE 應(yīng)用程序遷移到基于 Blueprint 的 OSGi 應(yīng)用程序,。這里描述的樣例應(yīng)用程序 Blether 提供一個(gè)基本社交消息服務(wù),允許用戶共享狀態(tài)更新以及查找和跟蹤其他用戶,。

接下來(lái)的部分概述樣例應(yīng)用程序,,并描述如何構(gòu)建和安裝它。

構(gòu)建 Blether 應(yīng)用程序

最初,,該應(yīng)用程序是使用 Spring 和 JPA 構(gòu)造的一個(gè)簡(jiǎn)單 Java EE 應(yīng)用程序,。在本練習(xí)期間,您要將其轉(zhuǎn)換為一個(gè) OSGi 應(yīng)用程序,,然后逐漸消除對(duì) Spring 的依賴性,。這不是作為一次性大批量遷移進(jìn)行的,您將看到如何單獨(dú)遷移應(yīng)用程序的各個(gè)區(qū)塊,,這樣應(yīng)用程序在遷移步驟間就仍然可用,。

為易于使用,樣例是作為若干 “快照” 提供的,,對(duì)應(yīng)于遷移過(guò)程(其中應(yīng)用程序功能完善)中的檢測(cè)點(diǎn),。您可以從初始代碼開始遵循練習(xí),一次遷移應(yīng)用程序的一部分,。另外,,您可以加入任何其他快照。構(gòu)建過(guò)程對(duì)于所有階段都是一樣的,。

本文以一個(gè) .zip 格式文件形式 提供可供下載的樣例,,該文件中還進(jìn)一步包含 .zip 文件,每個(gè)文件對(duì)應(yīng)于開發(fā)過(guò)程中的每個(gè)階段(快照),,還有一個(gè)腳本目錄,。腳本目錄包含用于安裝和卸載應(yīng)用程序的 python 腳本。所有快照 .zip 文件的結(jié)構(gòu)都一樣:一個(gè)頂級(jí)樣例目錄,,名為 sample,,包含頂級(jí)構(gòu)建文件以及持久性和 Web 組件子目錄。兩個(gè)子目錄都包含一個(gè) src 源文件目錄以及一個(gè)構(gòu)建文件和一個(gè)依賴描述符(ivy.xml),。Web 和持久性目錄包含一個(gè)資源目錄,。需要更改的大部分配置文件都位于資源的子目錄,。

要構(gòu)建應(yīng)用程序,從 “下載” 部分將適當(dāng)?shù)拇a快照(首先是 SampleInitial.zip 存檔)解壓到您的工作區(qū)目錄,。導(dǎo)航到樣例目錄,在這里通過(guò)命令行運(yùn)行 ant,。這將首先通過(guò)下載 Apache Ivy 然后下載構(gòu)建依賴項(xiàng)來(lái)引導(dǎo)項(xiàng)目,。這一步需要一個(gè)實(shí)用的互聯(lián)網(wǎng)連接,因?yàn)樗幸蕾図?xiàng)都取自中央 maven 存儲(chǔ)庫(kù),。之后,,將為持久性 JAR(或捆綁包)和 Web 模塊構(gòu)建兩個(gè)子項(xiàng)目,最后將在 build/lib 目錄中的最高一級(jí)創(chuàng)建 EAR 或 EBA,。

盡管命令行是構(gòu)建項(xiàng)目的一個(gè)不錯(cuò)的地方,,在實(shí)際編輯 Java 代碼時(shí) IDE 是一個(gè)更好的選擇。下面的遷移步驟假定您配有支持基本重構(gòu)的 IDE,,比如將類移入不同的程序包,,重命名字段,以及確定導(dǎo)入,。要在 Eclipse 中設(shè)置項(xiàng)目,,執(zhí)行以下步驟。生成的項(xiàng)目概要是:

  1. 創(chuàng)建一個(gè)新的 Java 項(xiàng)目,,命名為 Blether,。
  2. 導(dǎo)入從上述 SampleInitial.zip 中解壓出來(lái)的樣例目錄(通過(guò) Import > File System)。
  3. 如上所述運(yùn)行頂級(jí) build.xml,。在 Eclipse 中,,這可以通過(guò)右鍵單擊 build.xml 文件并選擇 Run As > Ant Build 來(lái)完成。
  4. 從構(gòu)建路徑中刪除 default 源文件夾,,添加 persistence/srcweb/src 作為源文件夾,。
  5. 將 persistence/lib 和 web/lib 中的所有庫(kù)添加到構(gòu)建路徑。

圖 1. Blether 應(yīng)用程序的 Eclipse 項(xiàng)目結(jié)構(gòu)
圖 1. Blether 應(yīng)用程序的 Eclipse 項(xiàng)目結(jié)構(gòu)

安裝 Blether 應(yīng)用程序

腳本化安裝過(guò)程對(duì)于所有快照是一樣的,。在首次安裝樣例時(shí),,必須創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)。您可以使用 scripts/createDb.sql 完成這個(gè)任務(wù),。之后,,scripts/bletherSampleUninstall.py 和 scripts/bletherSampleInstall.py 用于安裝和卸載應(yīng)用程序。下面的步驟針對(duì) Windows? 平臺(tái),。如果您使用 Linux?,,只需將 *.bat 替換為 *.sh

  1. createDb.sql 設(shè)置樣例應(yīng)用程序需要的數(shù)據(jù)庫(kù),。它只需要通過(guò) ${WAS_INSTALL_ROOT}/derby/bin/embedded/ij.bat createDb.sql 運(yùn)行一次,。
  2. bletherSampleInstall.py 安裝樣例應(yīng)用程序,,并創(chuàng)建手動(dòng)安裝所需的數(shù)據(jù)源。要安裝樣例,,運(yùn)行 ${WAS_PROFILE_ROOT}/bin/wsadmin.bat -f bletherSampleInstall.py fullInstall <server name> <node name> <path to sample binary>,,其中服務(wù)器和節(jié)點(diǎn)名稱是指 WebSphere Application Server 和節(jié)點(diǎn)的名稱,“path to sample binary” 是指要安裝的 EAR 或 EBA 文件的完全限定名,。
  3. bletherSampleUninstall.py 卸載樣例應(yīng)用程序,,也可以選擇性地卸載數(shù)據(jù)源。要運(yùn)行它,,像這樣調(diào)用 wsadmin 腳本:${WAS_PROFILE_ROOT}/bin/wsadmin.bat -f bletherSampleUninstall.py <mode>,,其中模式可以是僅限應(yīng)用程序或全部。

使用 Blether 應(yīng)用程序

在構(gòu)建樣例之后,,導(dǎo)航到 <WAS_DEFAULT_HOST>/blether,。這將向您呈現(xiàn)歡迎面板。首次使用應(yīng)用程序時(shí),,您需要?jiǎng)?chuàng)建一個(gè)用戶 ID,。為此,進(jìn)入注冊(cè)鏈接并填充表單,。注冊(cè)您的 ID 之后,,您將會(huì)被帶到主應(yīng)用程序面板。這個(gè)主界面顯示您自己和您跟蹤的那些用戶的狀態(tài)消息,,其中有一個(gè)用于發(fā)布新消息的文本框,。

要驗(yàn)證應(yīng)用程序在運(yùn)行,發(fā)布一條狀態(tài)消息,,然后登出并創(chuàng)建一個(gè)新用戶,。有了新用戶,您可以從右邊的用戶選項(xiàng)卡跟蹤第一個(gè)用戶,。這將列出系統(tǒng)知道的所有用戶,。單擊第一個(gè)用戶會(huì)將您帶到一個(gè)個(gè)人資料頁(yè)面,您可以在這里選擇跟蹤用戶,。您最初創(chuàng)建的狀態(tài)消息會(huì)出現(xiàn)在您的主狀態(tài)選項(xiàng)卡上,。

對(duì)應(yīng)用程序功能的這個(gè)最低限度的示范足以測(cè)試應(yīng)用程序到一個(gè) OSGi 應(yīng)用程序的轉(zhuǎn)換。


回頁(yè)首

遷移階段 1:將 Blether 打包為一個(gè) OSGi 應(yīng)用程序

一個(gè) OSGi 應(yīng)用程序包(或 EBA)的結(jié)構(gòu)很類似于一個(gè) Java EE 應(yīng)用程序存檔(EAR)的結(jié)構(gòu),。一個(gè) EBA 由零個(gè)或多個(gè)捆綁包組成,,打包在一個(gè)帶有可選應(yīng)用程序清單(APPLICATION.MF)的 .zip 格式存檔中,而且有一個(gè) .eba 擴(kuò)展名,。相比之下,,一個(gè) EAR 文件包含一個(gè)或多個(gè)模塊,打包在一個(gè)帶有應(yīng)用程序 XML 的 .zip 格式存檔中,,且有一個(gè) .ear 擴(kuò)展名,。


圖 2. EAR 的結(jié)構(gòu)
圖 2. EAR 的結(jié)構(gòu)

EBA 和 EAR 之間的主要區(qū)別在于,,EAR 幾乎總是包含存檔內(nèi)的所有模塊,且必須包含應(yīng)用程序 XML,,而 EBA 通常僅包含應(yīng)用程序清單(APPLICATION.MF),,且捆綁包理想情況下取自一個(gè)捆綁包存儲(chǔ)庫(kù)。(參見 Best practices for developing and working with OSGi applications, #9,。)從 EBA 外引用捆綁包是通過(guò) APPLICATION.MF 文件中的配置實(shí)現(xiàn)的,。默認(rèn)情況下,如果未指定 APPLICATION.MF 或 Application-Content 頭,,假定應(yīng)用程序由 EBA 內(nèi)存在的每個(gè)捆綁包形成。這個(gè)默認(rèn)行為表示不可能有一個(gè)不包含捆綁包也不包含 APPLICATION.MF 的 EBA,。如果 APPLICATION.MF 不定義一個(gè) Application-Content,,EBA 不包含捆綁包也是無(wú)效的。


圖 3. EBA 結(jié)構(gòu)示例,,含有和不含內(nèi)容的情況下
圖 3. EBA 結(jié)構(gòu)示例,,含有和不含內(nèi)容的情況下

本文中描述的前幾個(gè)遷移階段依賴于使用默認(rèn)的 OSGi 應(yīng)用程序行為。也就是說(shuō),,盡管您會(huì)在該階段生成一個(gè) EBA,,它不會(huì)包含應(yīng)用程序清單。您還要將文件 sample/resources/META-INF/application.xml 留在 EBA 中,,因?yàn)?OSGi 功能包可以使用文件中的信息預(yù)先填充一些配置選項(xiàng),。

在利用任何 OSGi 功能之前,您必須讓 Blether 樣例作為一個(gè) OSGi 應(yīng)用程序運(yùn)行,。這意味著 EAR 內(nèi)的 Java EE 模塊需要轉(zhuǎn)化成 OSGi 包,。對(duì)于 EBA 內(nèi)的一個(gè) WAR 模塊,這個(gè)轉(zhuǎn)換可以自動(dòng)執(zhí)行,,不過(guò)最好的做法是在將 WAR 模塊添加到 EBA 之前將其轉(zhuǎn)化為一個(gè) OSGi 包,。必須手動(dòng)轉(zhuǎn)換 EAR 內(nèi)的任何其他項(xiàng)目。

將持久性 JAR 轉(zhuǎn)化成一個(gè)捆綁包

要將 Blether 應(yīng)用程序轉(zhuǎn)化成一個(gè) OSGi 應(yīng)用程序,,首先將持久性 JAR 轉(zhuǎn)化成一個(gè) OSGi 包,;更具體地說(shuō)是一個(gè)持久性包,因?yàn)樵摪?JAR 內(nèi)容,。

將任何實(shí)用程序 JAR 轉(zhuǎn)化成包的第一步是,,您需要添加一個(gè)適當(dāng)?shù)睦壈鍐蔚?JAR。捆綁包清單根據(jù)(符號(hào))名稱和版本以及捆綁包的依賴項(xiàng)信息定義模塊的身份,,比如它提供的包和包內(nèi)的類需要的包,。

對(duì)于大型 JARs 來(lái)說(shuō)恰當(dāng)好處地做到后半部分有點(diǎn)棘手。但是,,有一個(gè)不錯(cuò)的工具(Peter Kriens 的 bnd 工具)可生成或檢查這個(gè)元數(shù)據(jù),。

對(duì)于 Blether 持久性 JAR,,轉(zhuǎn)換簡(jiǎn)單明了,因此沒必要使用工具,??v觀兩個(gè) JPA 類(~sample/persistence/src 目錄下),很明顯 javax.persistence 是除 java.* 類之外惟一需要的包,。因?yàn)槟枰谄渌鼉?nèi)使用來(lái)自這個(gè)包的兩個(gè)類,,您將需要導(dǎo)出其在清單中的包。清單 1 顯示 MANIFEST.MF 中需要的所有東西,。


清單 1. 一個(gè)持久性包清單樣例
            Manifest-Version: 1
            Bundle-ManifestVersion: 2
            Bundle-SymbolicName: com.ibm.ws.eba.example.blether.persistence
            Bundle-Version: 1.0.0
            Import-Package: javax.persistence;version="[1.0.0,2.0.0)"
            Export-Package: com.ibm.ws.eba.example.springmigration;version="1.0.0"
            Meta-Persistence:
            

注意,,導(dǎo)出和導(dǎo)入的程序包有其自己的版本屬性。OSGi 允許將版本分配給程序包以及整個(gè)捆綁包,,此外這些版本是完全獨(dú)立的,。程序包版本是對(duì)程序包(而非捆綁包)的用戶很重要的版本,因?yàn)槌绦虬姹居糜诖_定類兼容性,。因?yàn)樗鼘?duì)捆綁包之間的兼容性如此重要,,為一個(gè)程序包導(dǎo)出指定一個(gè)明確的版本是應(yīng)當(dāng)一直遵循的一個(gè)最佳實(shí)踐。

OSGi JPA 服務(wù)規(guī)范定義 JPA 1.0 程序包的版本是 1.0.0,,最佳實(shí)踐版本控制策略規(guī)定,,達(dá)到(但不包括)下一個(gè)主要版本的任何版本都將是兼容的。因此,,您可以為程序包導(dǎo)入指定一個(gè)版本范圍,,使用標(biāo)準(zhǔn) OSGi 語(yǔ)法表示您需要一個(gè)從版本 1.0.0(包括)到版本 2.0.0(不包括)的版本范圍。要知道程序包的版本不總是匹配它所來(lái)自于的規(guī)范的版本,。在本例中,,javax.persistence 的版本 1.0.0 來(lái)自 JPA 1.0,但是 JPA 2.0 對(duì)應(yīng)于 javax.persistence 1.1.0,。(參見 開發(fā)和使用 OSGi 應(yīng)用程序的最佳實(shí)踐,,#4。)注意,,“1.0.0” 的版本范圍不同于 “[1.0.0,1.0.0]”,。沒有定義最大值的版本范圍可延伸到無(wú)窮遠(yuǎn)。

總之,,該步驟所需的就是創(chuàng)建一個(gè)名為 MANIFEST.MF 的文件,,在 persistence/resources/META-INF/ 目錄中包含上面顯示的內(nèi)容。

Blether 持久性配置的更改

一個(gè)持久性 JAR(或持久性捆綁包)定義 JPA 運(yùn)行時(shí)會(huì)使用的持久性類和持久性單元,,以 EntityManagerFactory 的形式將持久性服務(wù)提供給應(yīng)用程序,。

持久性配置文件 persistence.xml 可位于一個(gè) OSGi 包中的任何位置。默認(rèn)位置是 META-INF/persistence.xml,;要支持其他位置,,JPA 擴(kuò)展程序預(yù)期將被告知使用 Meta-Persistence 在哪里可以找到 persistence.xml 文件:捆綁包清單中的標(biāo)頭,,如上所示。(根據(jù) JAR 規(guī)范,,要讓標(biāo)頭有效,,需要一個(gè)尾隨空格。)

如樣例清單所示,,存在沒有位置的 Meta-Persistence 頭,,這指示 JPA 擴(kuò)展程序查找其默認(rèn)位置中的持久性配置文件 META-INF/persistence.xml??梢允褂枚禾?hào)分隔的路徑指定其他位置,,包括嵌套 jars 的路徑,例如,,Meta-Persistence:jpa.xml, persistence.jar!/JPA/persistence.xml,。

一般而言,需要對(duì) persistence.xml 文件做少許更改來(lái)讓它們?cè)谝粋€(gè) OSGi 框架中工作,。通常需要更改的惟一部分是對(duì) JTA 和非 JTA 數(shù)據(jù)源的 JNDI 引用。在一個(gè) Java EE 場(chǎng)景中,,這些數(shù)據(jù)源通常通過(guò)一個(gè) java:comp/env 名稱空間查詢,,通過(guò)一個(gè) Web 模塊資源引用綁定。(這實(shí)際上是針對(duì)供應(yīng)商的一個(gè)選項(xiàng),,不是由 JPA 規(guī)范所定義,,規(guī)范只需要在這些元素中支持全局 JNDI 名稱。)

在樣例中,,數(shù)據(jù)源 JNDI 名稱不再適用于持久性捆綁包,,因?yàn)樗鼪]有相關(guān)的 java:comp 名稱空間(不同于 Web 模塊,該模塊仍然有一個(gè)用于向后兼容性的名稱空間),。在該樣例中,,您將遵循 JPA 規(guī)范,并將數(shù)據(jù)源直接映射到全局 JNDI,。當(dāng)然有一個(gè)用于使用持久性捆綁包的資源引用的機(jī)制,,這實(shí)際上是最佳實(shí)踐,但是這將讓您偏離本文主題,。產(chǎn)生的持久性描述符如清單 2 所示,。


清單 2. 一個(gè) OSGi 兼容的 persistence.xml
            <persistence xmlns="http://java./xml/ns/persistence"
            version="1.0">
            <persistence-unit name="sampleJPAPersistenceUnit"
            transaction-type="JTA">
            <jta-data-source>jdbc/userdb</jta-data-source>
            <non-jta-data-source>jdbc/nonXAdb</non-jta-data-source>
            <class>com.ibm.ws.eba.example.springmigration.Post</class>
            <class>com.ibm.ws.eba.example.springmigration.UserInfo</class>
            <exclude-unlisted-classes/>
            </persistence-unit>
            </persistence>
            

總之,第二步,,也就是對(duì) Blether 樣例進(jìn)行更改的步驟,,就是要修改 sample/persistence/resources/META-INF/persistence.xml 文件來(lái)匹配上述樣例。

Blether Web 模塊的更改

可以使用與對(duì)持久性模塊所做的類似的更改來(lái)將 EAR 中的 Web 模塊轉(zhuǎn)化成一個(gè) OSGi 包,。在本例中,,我們不使用 Meta-Persistence 頭來(lái)表示捆綁包是一個(gè)持久性包,,而是使用一個(gè) Web-ContextPath 頭來(lái)表示捆綁包是一個(gè) Web 應(yīng)用程序包(WAB)。您將在稍后的轉(zhuǎn)換中執(zhí)行這一步,,但是對(duì)于這個(gè)階段,,您要依賴于 WebSphere Application Server 執(zhí)行的自動(dòng)轉(zhuǎn)換。

Blether WAR 中的 Spring 上下文通過(guò) Web 模塊的本地 JNDI 查詢它使用的 EntityManagerFactory,,其中它由模塊的 web.xml 文件中的一個(gè) persistence-unit-ref 所映射,。由于持久性單元不再由 Java EE 定義,因此這樣的名稱不會(huì)由 OSGi JPA 運(yùn)行時(shí)填充,。相反地,,JPA 運(yùn)行時(shí)使用主要 OSGi 集成機(jī)制、OSGi 服務(wù)注冊(cè)表發(fā)布持久性單元(即 EntityManagerFactory),。不過(guò)這不是個(gè)問(wèn)題,,因?yàn)?OSGi JNDI 規(guī)范允許應(yīng)用程序使用 osgi:service 名稱空間將 JNDI 用作 OSGi 服務(wù)注冊(cè)表的一個(gè)集成層。

因此,,Web 模塊所需的惟一變更是更改描述符文件 sample/web/resources/WEB-INF/springapp-service.xml 中的這一行,,從:

<jee:jndi-lookup id="entityManagerFactory" jndi-name="jpa/emf"/>

到:

<jee:jndi-lookup id="entityManagerFactory" lookup-on-startup="false" proxy-interface="javax.persistence.EntityManagerFactory" jndi-name="osgi:service/javax.persistence.EntityManagerFactory"/>

這如何工作?首先,,新 JNDI 名稱指示處理程序從在 javax.persistence.EntityManagerFactory 接口下發(fā)布的服務(wù)注冊(cè)表返回服務(wù),。因此,不要根據(jù)單元名查詢 JPA 服務(wù),,而是僅使用這里的接口,。該查詢不含糊,因?yàn)?OSGi 應(yīng)用程序是孤立的且 Blether 僅定義單一持久性單元,。在一個(gè)擁有多個(gè)持久性單元的場(chǎng)景中,,可使用一個(gè) LDAP 樣式過(guò)濾器根據(jù)持久性單元限制選擇。例如,,JNDI 名稱 osgi:service/javax.persistence.EntityManagerFactory/(osgi.unit.name=sampleJPAPersistenceUnit) 會(huì)僅選擇 EntityManagerFactory 服務(wù),,其中將規(guī)范定義的屬性 osgi.unit.name 設(shè)置為持久性單元的名稱;在該例中為 sampleJPAPersistenceUnit,。

對(duì) Spring 應(yīng)用程序上下文的更改還通過(guò)將 lookup-on-startup 設(shè)置為 false 添加延遲層到 JNDI 查詢,,這也需要指定 proxy-interface 屬性。設(shè)置這個(gè)屬性之后,,Spring 容器僅會(huì)在首次需要時(shí)檢索 EntityManagerFactory 服務(wù),。添加這個(gè)的目的是消除 Web 模塊與持久性捆綁包之間存在的一個(gè)競(jìng)爭(zhēng)狀態(tài)。在 Java EE 中精心安排了這兩個(gè)模塊的啟動(dòng),,以便在繼續(xù)后續(xù)啟動(dòng)任務(wù)之前創(chuàng)建任何資源,,這以一個(gè)定義明確的方式發(fā)生。相比之下,OSGi 應(yīng)用程序和 OSGi 運(yùn)行時(shí)使用一組松耦合的協(xié)作捆綁包,,且通常異步完成其各自的任務(wù),。這將實(shí)現(xiàn)更快速的啟動(dòng)以及更靈活和健壯的應(yīng)用程序,但是通常需要額外延遲,,因?yàn)閷?duì)于啟動(dòng)順序沒有保證,。

在該階段,您還可以選擇刪除 web.xml 中的 persistence-unit-ref 元素,,因?yàn)樗鼈儾辉儆米魅魏斡猛?。但是它們的存在不?huì)導(dǎo)致任何問(wèn)題。

構(gòu)建步驟 1 的樣例應(yīng)用程序

此時(shí),,您已經(jīng)做了階段 1 所需的所有代碼更改,。與此遷移階段對(duì)應(yīng)的代碼可在 SampleStage1.zip 中找到。然而,,由于您需要構(gòu)建一個(gè) EBA 而非 EAR,,您需要對(duì)構(gòu)建腳本 sample/persistence/build.xml 和 sample/build.xml 做一些小的更改。

在 sample/persistence/build.xml 腳本中:

  1. 向 jar 任務(wù)添加一個(gè)清單屬性(例如 manifest="resources/META-INF/MANIFEST.MF"),。
  2. 添加一個(gè)代碼行,,去除 jar 任務(wù)內(nèi)的文件集中的 MANIFEST.MF;例如:

    <fileset dir="${basedir}/resources" includes="**/*">
    <exclude name="META-INF/MANIFEST.MF" />
    </fileset>

在 sample/build.xml 腳本中:

  1. 不創(chuàng)建 blether.ear,,而是創(chuàng)建一個(gè)名為 blether.eba 的 .zip 文件,;例如, <zip destfile="build/lib/blether.eba">,。記住要將終止的 /ear> 替換為 /zip>,。
  2. 刪除從 EAR 文件中排除 application.mf 的三個(gè)代碼行,,并添加一個(gè)代碼行(<fileset dir="resources" includes="**/*" />),,確保它包含在 blether.eba 中。

在這些更改之后或通過(guò) SampleStage1.zip 快照進(jìn)行重建時(shí),,將在 build/lib 中創(chuàng)建一個(gè)新的 OSGi 應(yīng)用程序二進(jìn)制文件,。應(yīng)用程序現(xiàn)在是功能齊全的一個(gè) OSGi 應(yīng)用程序。在 WebSphere Application Server 中測(cè)試它,,即首先使用 scripts/bletherSampleUninstall.py 腳本刪除上一版本,,之后使用 scripts/bletherSampleInstall.py 腳本安裝 EBA。驗(yàn)證您可以運(yùn)行 Blether 應(yīng)用程序,。


回頁(yè)首

遷移階段 2. 從 Spring 到 OSGi Blueprint Container

在上一節(jié),,您將 Blether 樣例應(yīng)用程序轉(zhuǎn)化成了一個(gè) OSGi 應(yīng)用程序。在做了這些變更之后,,下一個(gè)任務(wù)是將 Spring 依賴性注入框架替換為 Blueprint 框架,。您還會(huì)看到如何僅使用標(biāo)準(zhǔn) Java EE APIs 替換常見的 Spring 實(shí)用工具,比如 JpaTemplate。

如同上一節(jié),,您將依次對(duì)持久性捆綁包和 Web 捆綁包進(jìn)行更改,。

重構(gòu) Blether 服務(wù)

您必須對(duì) Blether 持久性服務(wù)進(jìn)行幾個(gè)更改。首先,,它取決于 JpaTemplate 類,。需要移除該依賴性。另外,,持久性服務(wù)在屬于 Web 模塊一部分的 BletherImpl* 中實(shí)現(xiàn),。分離表示層(Web 模塊)和業(yè)務(wù)(或持久性)層會(huì)更行得通。為此,,您要將 Blether 服務(wù)遷移到持久性捆綁包,,從這里 Web 模塊可以通過(guò) OSGi 服務(wù)注冊(cè)表訪問(wèn)它。這還將為您提供機(jī)會(huì)來(lái)引入第一部分 Blueprint,。

在 Blether 實(shí)現(xiàn)中不要使用 JpaTemplate

Blether 服務(wù)使用 Spring 框架提供的 JpaTemplate 實(shí)用工具類來(lái)為 JPA 添加其他方法,。JpaTemplate 效仿 javax.persistence.EntityManager 接口,但不真正實(shí)現(xiàn)它,。這表示,,JpaTemplate 上的絕大多數(shù)方法在標(biāo)準(zhǔn)接口中也可用,特別是基本接口:persist,、merge 和 find,。

移除依賴性的第一步是要在 Blether 服務(wù)類(BletherImpl.java)的開始將 org.springframework.orm.JpaTemplate import 替換為 javax.persistence.EntityManager。另外還需要添加 import javax.persistence.PersistenceContext;,。

其次,,您需要將注釋從對(duì)應(yīng)于 JpaTemplate 或 javax.persistence.EntityManagerFactory 的 @PersistenceUnit 更改為對(duì)應(yīng)于 javax.persistence.EntityManager 的 @PersistenceContext。您還要將字段 jpaTemplate 重命名為誤導(dǎo)性小的名稱,,比如 persistenceService,。

從清單 3 中所示的代碼入手應(yīng)用上述更改。結(jié)果應(yīng)當(dāng)如清單 4 所示,。


清單 3. Blether 服務(wù)持久性上下文注入
            @PersistenceUnit(unitName = "sampleJPAPersistenceUnit")
            private JpaTemplate jpaTemplate;
            public void setJpaTemplate(JpaTemplate j)
            {
            jpaTemplate = j;
            }
            


清單 4. 修改的 Blether 服務(wù)持久性上下文注入
            @PersistenceContext(unitName = "sampleJPAPersistenceUnit")
            private EntityManager persistenceService;
            public void setPersistenceService(EntityManager em)
            {
            persistenceService = em;
            }
            

在應(yīng)用這些更改之后,,全局性地將 jpaTemplate.find 替換為 persistenceUnit.find 應(yīng)當(dāng)會(huì)讓文件中的四個(gè)編譯錯(cuò)誤對(duì)應(yīng)于使用 JpaTemplate 的額外功能的情況,EntityManager 中不提供這些功能,。特別地,,您會(huì)缺少 find(String, Object ...) 方法。需要更改的 4 個(gè)方法是:

  • checkEmailUniqueness
  • getPostsByUser
  • getPostsForUserProfile
  • searchUserName

例如,,getPostsByUser 方法需要從清單 5 所示代碼更改為清單 6 所示代碼,。


清單 5. 使用 JpaTemplate 的 getPostsByUser
            @SuppressWarnings("unchecked")
            public List<Post> getPostsByUser(String username)
            {
            List<Post> result = jpaTemplate.find(getMyPostsQuery, username);
            return result;
            }
            


清單 6. 僅使用 JPA 標(biāo)準(zhǔn)接口的 getPostsByUser
            @SuppressWarnings("unchecked")
            public List<Post> getPostsByUser(String username)
            {
            Query query = persistenceService.createQuery(getMyPostsQuery);
            query.setParameter(1, username);
            return query.getResultList();
            }
            

需要做相同的更改來(lái)修復(fù)其余三個(gè)編譯錯(cuò)誤。因此,,checkEMailUniqueness 方法變?yōu)榍鍐?7 中所示的代碼,。


清單 7. 僅使用 JPA 標(biāo)準(zhǔn)接口的 checkEMailUniqueness
            @SuppressWarnings("unchecked")
            public boolean checkEMailAddressUniqueness(String emailAddress)
            {
            boolean result = false;
            Query query = persistenceService.createQuery(uniqueEmailAddressQuery);
            query.setParameter(1, emailAddress);
            List<UserInfo> users = (List<UserInfo>) query.getResultList();
            if (users.isEmpty()) {
            result = true;
            }

getPostsForUserProfile 方法變?yōu)榍鍐?8 中所示的代碼。


清單 8. 僅使用 JPA 標(biāo)準(zhǔn)接口的 getPostsForUserProfile
            @SuppressWarnings("unchecked")
            public List<Post> getPostsForUserProfile(String userName)
            {
            Query query = persistenceService.createQuery(getPostsVisibleToUserQuery);
            query.setParameter(1, userName);
            return query.getResultList();
            }

最后,searchUsername(String usernameFilter) 變?yōu)榍鍐?9 中所示的代碼,。


清單 9. 僅使用 JPA 標(biāo)準(zhǔn)接口的 searchUsername
            public List<UserInfo> searchUsername(String usernameFilter)
            {
            usernameFilter += "%";
            Query query = persistenceService.createQuery(searchUserNameQuery);
            query.setParameter(1, usernameFilter);
            return query.getResultList();
            }

此時(shí),,您完成了對(duì) BletherImpl.java 類的更改。

將 Blether 服務(wù)遷移到持久性捆綁包中

您需要將使用 JPA 服務(wù)的應(yīng)用程序邏輯從 Web 模塊遷移到持久性捆綁包,。正是這一階段真正需要一個(gè)好的 Java IDE,,比如 Eclipse。(描述重構(gòu) Blether 代碼所需的文件更改對(duì)于本文來(lái)說(shuō)沒有任何價(jià)值,,因?yàn)?IDE 會(huì)為您料理這一切,。)

要重構(gòu):

  1. 將 BletherUserInterface.java 類遷移到持久性捆綁包中的 com.ibm.ws.example.springmigration 程序包。
  2. 將 BletherImpl.java 類遷移到持久性捆綁包中的 com.ibm.ws.example.springmigration.impl,。

這些變更都不需要更新持久性捆綁包的清單,,因?yàn)闆]有導(dǎo)入或?qū)С鲂鲁绦虬?/p>

重新連接 Blether 服務(wù)來(lái)使用 Blueprint

現(xiàn)在 Blether 服務(wù)存在于持久性捆綁包中,您需要確保它可由 Blether WAR 中的 servlets 訪問(wèn),。正如您所看到的,,交換服務(wù)的地方(在一個(gè) OSGi 環(huán)境中)是 OSGi 服務(wù)注冊(cè)表。您可以通過(guò) osgi:service 名稱空間暫時(shí)連接到 OSGi 注冊(cè)表,。在 Spring 描述符(sample/web/resources/WEB-INF/springapp-service.xml)中,,刪除 bletherService bean、EntityManagerFactory 的 JNDI 查詢和 jpatemplate bean,。在其位置中,,您希望為 Blether 服務(wù)執(zhí)行一個(gè)查詢,如清單 10 所示,。


清單 10. 從服務(wù)注冊(cè)表獲取持久性服務(wù)
            <jee:jndi-lookup lookup-on-startup="false" id="bletherService"
            proxy-interface="com.ibm.ws.eba.example.springmigration.BletherUserInterface"
            jndi-name="osgi:service/com.ibm.ws.eba.example.springmigration.BletherUserInterface"/>
            

您還需要讓 Blether 服務(wù)在服務(wù)注冊(cè)表中可用,。在簡(jiǎn)單 OSGi 中,實(shí)現(xiàn)這一點(diǎn)的方法是添加一個(gè)捆綁包激活器到持久性捆綁包來(lái)實(shí)例化 Blether 服務(wù),,然后使用 org.osgi.framework.BundleContext 上的 API 來(lái)將其發(fā)布到服務(wù)注冊(cè)表,。然而這將是不必要的框架,可通過(guò)使用 Blueprint 這樣的依賴性注入框架來(lái)避免,。

您要添加一個(gè) Blueprint 描述符到持久性捆綁包,。為此,,使用清單 11 中所示的內(nèi)容創(chuàng)建 sample/persistence/resources/OSGI-INF/blueprint/blueprint.xml,。


清單 11. 持久性捆綁包的 Blueprint 描述符
            <blueprint xmlns="http://www./xmlns/blueprint/v1.0.0">
            <bean id="bletherImpl"
            class="com.ibm.ws.eba.example.springmigration.impl.BletherImpl" />
            <service ref="bletherImpl"
            interface="com.ibm.ws.eba.example.springmigration.BletherUserInterface" />
            </blueprint>
            

如您所料,Blueprint 描述符非常類似于 Spring 描述符,。頂級(jí)元素和名稱空間聲明改變了,,但是 bean 聲明基本一樣。服務(wù)元素更有趣,。它將 bletherImpl bean 發(fā)布到 BletherUserInterface 接口下的服務(wù)注冊(cè)表中,。顯式地指定接口似乎有點(diǎn)限制,且在重命名接口或?qū)⒔涌谶w移到另一個(gè)程序包時(shí)需要更改 XML。一個(gè)替代方法是指定屬性 auto-export=”interfaces”,,它會(huì)針對(duì) bean 實(shí)現(xiàn)的所有接口將 bean 注冊(cè)為一個(gè) OSGi 服務(wù),。在該示例中,兩種方法產(chǎn)生同樣的結(jié)果,。

最后的區(qū)別是 JPA 服務(wù)的注入,,這在 Blueprint 描述符中沒有。有了 Blueprint 和 OSGi JPA,,EntityManager 的注入基于 BletherImpl 中指定的 @PersistenceContext 發(fā)生在幕后,。(這個(gè)注入僅針對(duì)由 Blueprint 容器管理的實(shí)例。)

這一需求可能不會(huì)總是得到滿足,。例如,,沒有方法可以匹配 JPA 注釋與工廠創(chuàng)建的 bean。對(duì)于這種情況,,有一個(gè)用于注入 JPA 服務(wù)的 Blueprint 擴(kuò)展名稱空間,,該機(jī)制還在僅使用注釋的情況下在幕后得到使用。清單 12 顯示在 Blueprint 中通過(guò)工廠類構(gòu)造 beans 所需的 Blueprint XML 示例,。(這僅供參考,,不在該遷移示例中使用。)


清單 12. 使用 JPA 擴(kuò)展的持久性捆綁包的 Blueprint 描述符
            <blueprint xmlns="http://www./xmlns/blueprint/v1.0.0"
            xmlns:jpa="http://aries./xmlns/jpa/v1.0.0">
            <bean id="bletherImpl"
            class="com.ibm.ws.eba.example.springmigration.impl.BletherFactory"
            factory-method=”createBletherService”>
            <jpa:context property=”entityManager” unitname=”sampleJPAPersistenceUnit” />
            </bean>
            <service ref="bletherImpl"
            interface="com.ibm.ws.eba.example.springmigration.BletherUserInterface" />
            </blueprint>

有了這些變更,,持久性捆綁包和核心應(yīng)用程序邏輯就安排妥當(dāng)了(OSGi)?,F(xiàn)在您可以重新構(gòu)建和重新安裝應(yīng)用程序來(lái)確保一切仍然運(yùn)作正常。此檢測(cè)點(diǎn)處的應(yīng)用程序在 SamepleStage2.zip 文件中提供,。


回頁(yè)首

遷移階段 3:更改 Blether Web 模塊來(lái)使用 Blueprint

遷移持久性層和應(yīng)用層之后,,現(xiàn)在您可以將注意力轉(zhuǎn)向其余 Web 層了。目標(biāo)在于將 Spring 描述符和特定于 Spring 的 APIs 替換為 Blueprint 和標(biāo)準(zhǔn) APIs,。您要分兩步處理這個(gè)任務(wù),。首先,消除對(duì) Spring 的 HttpRequestHandler 機(jī)制的依賴性,,然后遷移 Spring 描述符,。

替換 HttpRequestHandler 機(jī)制

對(duì) Spring Web 應(yīng)用程序的一個(gè)常見顧慮是,Web 描述符中聲明的 servlets 由 Web 容器而非 Spring 管理,。這表示,,它們不能使用 Spring 依賴性注入框架提供的優(yōu)勢(shì)。此外,,需要為 servlets 編寫橋接邏輯,,以使用在 Spring 描述符中定義的 beans。這是個(gè)不太理想的事態(tài),。所幸,,Spring 框架包含一個(gè)實(shí)用工具 HttpRequestHandlerServlet,,它處理橋接邏輯且委托給 HttpRequestHandler。這些為 Spring 用戶提供與 servlet 功能同等的功能,。

作為一個(gè)簡(jiǎn)單依賴性注入框架,,Blueprint 對(duì)于 Web 容器與 Blueprint 容器之間的橋接存在完全相同的問(wèn)題。但是,,在這種情況下沒有標(biāo)準(zhǔn)化的實(shí)用工具,,比如 HttpRequestHandlerServlet。不過(guò)您可以開發(fā)一個(gè)可重用機(jī)制來(lái)提供相同的功能,。

創(chuàng)建 AppRequestHandler 接口

您需要在 /web/src/com/ibm/ws/eba/example/springmigration/web/ 中創(chuàng)建一個(gè)新接口來(lái)封裝與 HttpRequestHandler 相同的功能,。該接口定義一個(gè)處理任意 HTTP 請(qǐng)求的 servlet 的一個(gè)通用抽象(清單 13)。


清單 13. AppRequestHandler 接口
            public interface AppRequestHandler {
            void handleRequest(HttpServletRequest arg0, HttpServletResponse arg1)
            throws ServletException, IOException;
            }

創(chuàng)建 ForwardServlet 類

您需要替換 HttpRequestHandlerServlet,,因?yàn)檫@一工具是特定于 Spring 的,,不適用于 Blueprint。從 Web 描述符的角度來(lái)看,,HttpRequestHandlerServlet 代表 Blether 使用的惟一 servlet,。它基于 servlet 名稱和 bean 名稱(預(yù)計(jì)會(huì)完全匹配)選擇目標(biāo) HttpRequestHandler。目前,,您要構(gòu)建稍微簡(jiǎn)單一點(diǎn)的東西,,有明確的名稱匹配配置。在 /web/src/com/ibm/ws/eba/example/springmigration/web/ 中創(chuàng)建如清單 14 所示的 ForwardServlet 類,。


清單 14. ForwardServlet 實(shí)現(xiàn)
            public class ForwardServlet extends HttpServlet {
            @Override
            protected void service(HttpServletRequest req,
            HttpServletResponse resp)
            throws ServletException, IOException
            {
            try {
            InitialContext ic = new InitialContext();
            AppRequestHandler handler = (AppRequestHandler)
            ic.lookup("osgi:service/" +
            AppRequestHandler.class.getName() + "/" +
            "(servlet.name=" + getServletName() + ")");
            if (handler != null) {
            handler.handleRequest(req, resp);
            } else {
            System.out.println("ERROR: No handler for servlet"+getServletName());
            }
            } catch (NamingException ne) {
            ne.printStackTrace();
            }
            }
            }

上述代碼沒有什么特別或新穎之處,。ForwardServlet 的惟一顧慮是查詢正確的 AppRequestHandler 并將傳入的請(qǐng)求轉(zhuǎn)發(fā)給它。作為一個(gè)集成機(jī)制,,您要再次使用 OSGi 服務(wù)注冊(cè)表,,像以前一樣通過(guò)一個(gè) JNDI 查詢予以訪問(wèn)。另外,,可通過(guò) osgi-bundlecontext 屬性從 servlet 上下文提供 Web 捆綁包的 BundleContext,。為了區(qū)分不同的請(qǐng)求處理程序,您需要一個(gè)額外的服務(wù)屬性 servlet.name,,該屬性預(yù)計(jì)會(huì)匹配傳入請(qǐng)求的 servlet 名稱,。

將 Spring 描述符轉(zhuǎn)化為 Blueprint

最后,該是時(shí)候?qū)⑵溆?Spring 描述符全部轉(zhuǎn)化成 Blueprint 了,。除了轉(zhuǎn)化語(yǔ)法差異(比如標(biāo)記名稱)之外,,您還需要使用適當(dāng)?shù)?servlet.name 服務(wù)屬性在服務(wù)注冊(cè)表中注冊(cè)請(qǐng)求處理程序。最后,,.jee,、.tx 和 .aop 等 Spring 擴(kuò)展名需要全部替換為適合的 Blueprint 擴(kuò)展名,。

創(chuàng)建 Blueprint XML

目前,,Spring 描述符類似于清單 15(細(xì)節(jié)省略),。


清單 15. Web 模塊的 Spring 描述符
            <beans xmlns="http://www./schema/beans"
            xmlns:tx="http://www./schema/tx"
            xmlns:aop="http://www./schema/aop"
            xmlns:jee="http://www./schema/jee">
            <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
            </tx:attributes>
            </tx:advice>
            <aop:config>
            <aop:pointcut id="servletRequest" expression=
            "execution(* com.ibm.ws.eba.example.springmigration.web.*.handleRequest(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="servletRequest"/>
            </aop:config>
            <bean id="RegistrationServlet"
            class="com.ibm.ws.eba.example.springmigration.web.Registration">
            <property name="bletherHandle">
            <ref bean="bletherService"/>
            </property>
            </bean>
            ... A lot more request handlers ...
            <jee:jndi-lookup lookup-on-startup="false" id="bletherService"
            proxy-interface="com.ibm.ws.eba.example.springmigration.BletherUserInterface"
            jndi-name="osgi:service/com.ibm.ws.eba.example.springmigration.BletherUserInterface"
            />
            <tx:jta-transaction-manager/>
            </beans>

下一步是創(chuàng)建一個(gè) Blueprint 描述符;即創(chuàng)建 sample/web/resources/OSGI-INF/blueprint.xml,。您可以通過(guò)查看 sample/web/resources/WEB-INF/springapp-service.xml 開始構(gòu)建該文件的內(nèi)容了,。

  • .jee 擴(kuò)展名僅用于通過(guò) JNDI 查詢 Blether 服務(wù)。但是 Blether 服務(wù)實(shí)際上存在于 OSGi 服務(wù)注冊(cè)表,,且 Blueprint 定義了一種更直接的方式,,通過(guò)引用元素使用來(lái)自 OSGi 服務(wù)注冊(cè)表的服務(wù)。因此,,不需要 .jee 功能且您不需要在 Blueprint 描述符中創(chuàng)建任何等同功能,。
  • .aop 和 .tx 擴(kuò)展名在 springapp-service.xml 中用于聲明圍繞所有請(qǐng)求處理程序的事務(wù)。實(shí)現(xiàn)這種聲明性事務(wù)的機(jī)制是通用且正交的,,基于內(nèi)容導(dǎo)向,。這意味著所有單個(gè)部分可獨(dú)立用于各種用途。Blueprint 還支持聲明性事務(wù),。

    具體而言,,您需要使用 http://aries./xmlns/transactions/v1.0.0 名稱空間,它定義一個(gè)元素,,為一個(gè)封閉的 bean 元素聲明事務(wù)性行為,。

    要注意這里描述的擴(kuò)展名、上面使用的 .jpa 擴(kuò)展名和基礎(chǔ)擴(kuò)展名機(jī)制是特定于 Apache Aries 項(xiàng)目的 Blueprint 實(shí)現(xiàn)的,,該項(xiàng)目屬于 OSGi 功能包的一部分,。目前在核心 Blueprint 規(guī)范中沒有定義好的擴(kuò)展名機(jī)制。

除了這些變更,,您需要為每個(gè)請(qǐng)求處理程序創(chuàng)建一個(gè)服務(wù)導(dǎo)出定義,。為此,使用已經(jīng)在持久性捆綁包的 Blueprint 描述符中引入的服務(wù)元素,。最后,,需要更改一些小的語(yǔ)法差異;例如,,一個(gè)屬性元素內(nèi)的 ref 元素有一個(gè) id 屬性,,而非 Spring 中使用的 bean 屬性。

Blueprint 描述符文件類似于清單 16,。


清單 16. Web 模塊的 Blueprint 描述符
            <blueprint xmlns="http://www./xmlns/blueprint/v1.0.0"
            xmlns:tx="http://aries./xmlns/transactions/v1.0.0">
            <bean id="RegistrationServlet"
            class="com.ibm.ws.eba.example.springmigration.web.Registration">
            <tx:transaction method="*" value="Required"/>
            <property name="bletherHandle" ref="bletherService" />
            </bean>
            <service ref="RegistrationServlet"
            interface="com.ibm.ws.eba.example.springmigration.web.AppRequestHandler">
            <service-properties>
            <entry key="name" value="RegistrationServlet" />
            </service-properties>
            </service>
            ... Repeat the bean definition and service element for each resource...
            <reference id="bletherService"
            interface="com.ibm.ws.eba.example.springmigration.BletherUserInterface" />
            </blueprint>

這比它替換的 Spring 描述符略微更冗長(zhǎng)些,。這主要是由于其他服務(wù)元素,而且事務(wù)現(xiàn)在是以 bean 為單位聲明的,,而非全局性聲明 — 不過(guò)如果您看一下 SampleStage3.zip 內(nèi)容,,您會(huì)看到一些 tx 元素實(shí)際上并不需要且已被刪除。使用擴(kuò)展名,,還可以通過(guò) Blueprint APIs(特別是 org.osgi.service.blueprint.container.BlueprintContainer)直接消除服務(wù)元素的開銷,,并根據(jù)名稱查詢 beans(類似于 HttpRequestHandlerServlet 所做的),。Blueprint 容器可以取自O(shè)SGi 服務(wù)注冊(cè)表(這不足為奇)。我們將在本文末尾返回該話題,。

清理 web.xml 文件

引用 Spring 的部分可以從 web/resources/web.xml 文件中刪除了,,這只表示要?jiǎng)h除 <context-param> 和 <listener> 部分。

清理 ivy.xml 文件

在該階段,,對(duì) Spring 框架的所有依賴性都被切斷,,且可以從 Web 項(xiàng)目的 ivy.xml 文件中刪除對(duì)應(yīng)的代碼行。只有三個(gè)依賴項(xiàng)仍然保留:javax.servlet,、javax.persistence 和 com.google.code.gson,。可以刪除 springapp-service.xml 文件,。

應(yīng)用程序所處階段在 SampleStage3.zip 快照中被捕獲,。如果愿意,您可以使用前面部分描述的 uninstall/install 腳本測(cè)試它,。


回頁(yè)首

遷移階段 4:收尾

在該階段,,完全將 Blether 應(yīng)用程序從 Spring 模型轉(zhuǎn)化為 OSGi 了,特別是 Blueprint 模型,。但是有一點(diǎn)清理工作還需要做,,這在前面的步驟中被省略了。最重要的是,,應(yīng)用程序依賴于應(yīng)用程序清單的自動(dòng)完成和 Web 模塊的自動(dòng)轉(zhuǎn)換,。雖然這些功能非常便于使用 OSGi 功能包快速轉(zhuǎn)換要運(yùn)行的應(yīng)用程序,但您通常會(huì)希望對(duì)生產(chǎn)中的應(yīng)用程序有更嚴(yán)格的控制,。例如,,自動(dòng)生成的應(yīng)用程序清單不允許細(xì)粒度更新。而且自動(dòng)轉(zhuǎn)換的 WAR 模塊將所有依賴項(xiàng)看作是可選的,,這樣 OSGi 解析程序就不會(huì)確保 Web 模塊的所有依賴項(xiàng)都存在,。

將 Web 模塊轉(zhuǎn)化為一個(gè) Web 應(yīng)用程序包

首先,您要將 Web 模塊轉(zhuǎn)化成一個(gè)合適的捆綁包,,這是創(chuàng)建一個(gè)完整應(yīng)用程序清單的先決條件,。正如在 OSGi 中,這一切都通常涉及到仔細(xì)制作合適的清單,。根據(jù) OSGi Web 應(yīng)用程序規(guī)范(OSGi Enterprise spec rev. 4.2, 128),,除了確定正確的 Import-Package 語(yǔ)句之外,一個(gè) Web 模塊尤其需要適當(dāng)?shù)卦O(shè)置捆綁包類路徑,,還要有一個(gè)標(biāo)頭來(lái)將捆綁包指示為一個(gè) Web 捆綁包,。將清單 17 中所示的內(nèi)容編輯到 sample/web/resources/META_INF/MANIFEST.MF 文件中。


清單 17. Blether Web 應(yīng)用程序包清單
            Manifest-Version: 1.0
            Bundle-ManifestVersion: 2
            Web-ContextPath: /blether
            Bundle-SymbolicName: com.ibm.ws.eba.example.blether.web
            Bundle-Version: 1.0.0
            Bundle-Classpath: WEB-INF/classes/,WEB-INF/lib/JSON4J.jar
            Import-Package: javax.servlet;version=2.5,
            javax.servlet.http;version=2.5,
            javax.el;version=2.1,
            javax.servlet.jsp;version=2.1,
            javax.servlet.jsp.el;version=2.1,
            javax.servlet.jsp.tagext;version=2.1,
            com.ibm.ws.eba.example.springmigration;version="[1.0.0,2.0.0)"
            

清單中的導(dǎo)入程序包頭是相當(dāng)不言自明的,。您需要 servlet API 程序包,,當(dāng)然還有來(lái)自持久性捆綁包的持久性實(shí)體和 BletherUserInterface 類,。捆綁包類路徑頭更有趣。該頭是必需的,,因?yàn)樵谝粋€(gè) Web 應(yīng)用程序(以及一個(gè) Web 應(yīng)用程序捆綁包)中,,類不在捆綁包的根部,,而是在 WEB-INF/classes 中,。而且,嵌入的庫(kù)存在于 WEB-INF/lib/*.jar 中,。OSGi 通過(guò) Bundle-Classpath 頭提供一個(gè)標(biāo)準(zhǔn)的機(jī)制來(lái)定義這些非標(biāo)準(zhǔn)的類路徑,,這里需要用到它們是因?yàn)?Web 應(yīng)用程序捆綁包不再?gòu)?Java EE Web 容器中使用的約定中受益。由于您在前面的步驟中刪除了所有 Spring 依賴項(xiàng),,需要提供的惟一 JAR 庫(kù)是 JSON,。再進(jìn)一步,就會(huì)很容易將該依賴項(xiàng)提取到其自己的捆綁包(元數(shù)據(jù)已存在)中,,從而進(jìn)一步將其 OSGi 化為 Web 捆綁包,。這留給您稍后做練習(xí)。

最后,,有一個(gè) Web-ContextPath 頭,。它主要有兩個(gè)功能。首先,,它指定安裝 Web 應(yīng)用程序所在的默認(rèn)上下文路徑,。但是在 WebSphere Application Server 上,安裝應(yīng)用程序時(shí)可重寫該默認(rèn)設(shè)置,。其次,,也是較為重要的一點(diǎn)是,它將捆綁包指示為一個(gè) Web 捆綁包,。因此與沒有 Meta-Persistence 的持久性捆綁包類似,,沒有 Web-ContextPath 頭的 Web 捆綁包不會(huì)被看作是 Web 捆綁包。

創(chuàng)建應(yīng)用程序清單

一個(gè) OSGi 應(yīng)用程序的應(yīng)用程序清單位于 .eba 存檔內(nèi)的 META-INF/APPLICATION.MF,,它描述一個(gè) OSGi 應(yīng)用程序的身份和邏輯內(nèi)容,。清單 18 顯示 Blether 應(yīng)用程序的一個(gè)樣例清單。


清單 18. Blether 應(yīng)用程序清單
            Manifest-Version: 1.0
            Application-Name: Blether spring migration sample
            Application-SymbolicName: blether.eba
            Application-Version: 1.0.0
            Application-Content: com.ibm.ws.eba.example.blether.persistence;version="[1.0.0,2.
            0.0)",com.ibm.ws.eba.example.blether.web;version="[1.0.0,2.0.0)"

有趣的部分主要是應(yīng)用程序內(nèi)容頭,。該頭定義應(yīng)用程序的邏輯內(nèi)容,;在本例中是 Web 捆綁包和持久性捆綁包。在以這種方式聲明內(nèi)容之后,,捆綁包不再需要包含在 .eba 存檔本身,。而是可以從捆綁包的一個(gè)外部存儲(chǔ)庫(kù)或 WebSphere Application Server 內(nèi)部捆綁包存儲(chǔ)庫(kù)中拉入捆綁包。要知道,,對(duì)于 com.ibm.ws.eba.example.blether.persistence;[1.0.0,2.0.0) 這樣一個(gè)版本范圍,,.eba 存檔與任何已定義捆綁包存儲(chǔ)庫(kù)之間可用的持久性捆綁包的最高可用版本會(huì)被用到,,不一定是 .eba 中包含的那一個(gè)。版本范圍的一個(gè)最終目的是要定義可以更新應(yīng)用程序中的捆綁包的界線,。例如,,在上述清單中,應(yīng)用程序可以由 1.0.0(包括)與 2.0.0(不包括)之間的任何版本的 Web 捆綁包和持久性捆綁包組成,。(參見 參考資料,。)

要為 Blether 樣例創(chuàng)建一個(gè)應(yīng)用程序清單,將清單 18 中的樣例代碼粘貼到 sample/resource/META-INF/APPLICATION.MF 中,。

ForwardServlet 的收尾工作

作為最后的改進(jìn),,再次看一下階段 3 中開發(fā)的 ForwardServlet。它有相當(dāng)多的 boilerplate Blueprint XML,,用于定義請(qǐng)求處理程序 beans,,然后通過(guò)正確的服務(wù)屬性將它們導(dǎo)出到服務(wù)注冊(cè)表。如果 ForwardServlet 使用了一個(gè)類似于 Spring 的 HttpRequestHandlerServlet 的約定優(yōu)于配置(convention-over-configuration)方法,,這會(huì)更整潔,,其中 bean 的 ID 預(yù)期匹配 web.xml 中定義的 servlet 名稱。

原來(lái)僅需一次小小的重寫就可以實(shí)現(xiàn)這一點(diǎn),。清單 13 顯示基本實(shí)現(xiàn),。不要從服務(wù)注冊(cè)表查詢特定 AppRequestHandler,而是要從那里為 Web 捆綁包獲取 BlueprintContainer,。然后將其用于獲取 ID 等于 servlet 名稱的 bean 實(shí)例,。(現(xiàn)在該實(shí)現(xiàn)取決于 Blueprint 接口,而非僅僅使用通用的服務(wù)注冊(cè)表,。)


清單 19. 使用約定優(yōu)于配置方法的 ForwardServlet
            import org.osgi.service.blueprint.container.BlueprintContainer;
            public class ForwardServlet extends HttpServlet {
            @Override
            protected void service(HttpServletRequest arg0,
            HttpServletResponse arg1)
            throws ServletException, IOException
            {
            try {
            InitialContext ic = new InitialContext();
            BlueprintContainer container = (BlueprintContainer) ic.lookup("osgi:service/"
            + "org.osgi.service.blueprint.container.BlueprintContainer/"
            + "(osgi.blueprint.container.symbolicname=com.ibm.ws.eba.example.blether.web)");
            AppRequestHandler handler = (AppRequestHandler)
            container.getComponentInstance(getServletName());
            if (handler != null) handler.handleRequest(arg0, arg1);
            else System.out.println("ERROR: No handler for servlet"+getServletName());
            } catch (NamingException ne) {
            ne.printStackTrace();
            }
            }
            }

除了更改 Java 代碼之外,,您還需要在捆綁包清單中聲明對(duì) Blueprint 的新依賴性,方法就是添加以下代碼到程序包導(dǎo)入頭:

org.osgi.service.blueprint.container;version="[1.0.0,2.0.0)"

將該代碼行添加到 MANIFEST.MF 文件中時(shí),,不要忘記在前一行的末尾加一個(gè)逗號(hào),。

Ivy 配置的更改

最后一次重新構(gòu)建應(yīng)用程序之前,還需要進(jìn)行一項(xiàng)更改來(lái)讓 Blueprint API 在編譯階段可用,。為此,,添加一個(gè)依賴性聲明:

<dependency org="org.osgi" name="org.osgi.compendium" rev="4.2.0" conf="*->*,!sources"/>

將其添加到 Web 項(xiàng)目中的 ivy.xml 中,而且要確保新的 JAR 不作為 WAR 文件的一部分打包,。后半部分實(shí)際上不重要,,因?yàn)樵?OSGi 中是為類搜索程序包導(dǎo)入,而非沖突情況下捆綁包的內(nèi)容,。


回頁(yè)首

結(jié)束語(yǔ)

本文完成了從 Blether Spring 應(yīng)用程序到 Blether OSGi 應(yīng)用程序的轉(zhuǎn)換,。將該示例作為一個(gè)模板來(lái)轉(zhuǎn)化您自己的 Spring 應(yīng)用程序并利用 OSGi 的優(yōu)勢(shì)。最終的完整樣例代碼可見于 SampleSnapshotFinal.zip 下載文件



回頁(yè)首

下載

描述 名字 大小 下載方法
樣例應(yīng)用程序 SpringMigrationStages.zip 240KB HTTP

關(guān)于下載方法的信息


參考資料

學(xué)習(xí)

獲得產(chǎn)品和技術(shù)

討論

作者簡(jiǎn)介

Valentin Mahrwald 是 IBM 赫斯利實(shí)驗(yàn)室的一名軟件工程師,。他積極參與 OSGi Applications Feature Pack for WebSphere Application Server 以及 Apache Aries 項(xiàng)目。在業(yè)余時(shí)間,,他追求在語(yǔ)言,、編程等方面的興趣。Valentin 獲得了約克大學(xué)數(shù)學(xué)和計(jì)算機(jī)科學(xué)專業(yè)的數(shù)學(xué)碩士學(xué)位,。

Tim Ward 是 WebSphere Application Server 的 OSGi Applications 特性的設(shè)計(jì)和開發(fā)主管,。他是 OSGi Enterprise Expert Group (EEG) 的積極參與者,其中他與別人合作完成了 OSGi JPA Service 規(guī)范,,目前主要領(lǐng)導(dǎo)幾個(gè) RFC,。Tim 也是 Apache Aries 項(xiàng)目的成員,一個(gè) JPA 提倡者,,同時(shí)也是 IBM 關(guān)鍵 Spring Framework 專家之一,。

Zoe Slattery是在英國(guó) IBM Hursley 工作的一名技術(shù)推廣者。目前她的興趣是 Enterprise OSGi,,特別是 Apache Aries 中開源 OSGi 組件的開發(fā),。過(guò)去,Zoe 曾在 IT 行業(yè)的很多領(lǐng)域工作過(guò)。她最初擔(dān)任 FORTRAN 程序員,,進(jìn)行用于密集數(shù)字計(jì)算的并行系統(tǒng)方面的工作,,管理歐洲中期天氣預(yù)報(bào)中心 (European Centre for Medium Range Weather Forecasts) 的數(shù)據(jù)存檔。作為一名管理者,,她一直在負(fù)責(zé)管理進(jìn)行 IBM 的 Java Virtual Machine 和 Java 類庫(kù)的開源實(shí)現(xiàn)的開發(fā)團(tuán)隊(duì),,最近,Zoe 致力于 PHP 測(cè)試案例的開發(fā),,使核心 PHP 測(cè)試案例超過(guò) 2 倍,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多