[转载]使用 Apache Geronimo 和 POJO 构建 SOA 框架
使用 Apache Geronimo 和 POJO 構(gòu)建 SOA 框架
在不考慮庫和框架強制執(zhí)行的應(yīng)用程序編程接口 (API) 約束的情況下進行軟件開發(fā),是一個非常誘人主張。它使許多人接受了普通舊式 Java? 對象(Plain Old Java? Object,POJO)編程的范例 —— 能夠在 Java 平臺上開發(fā)軟件,而無需使用多余的接口或第三方 API。Apache Geronimo 框架為構(gòu)建復(fù)雜應(yīng)用程序和服務(wù)的 POJO 開發(fā)提供了一個可靠的基礎(chǔ)設(shè)施。本文介紹 Geronimo 框架的一些組件和技巧,用于通過 POJO 策略來實現(xiàn)成功的、面向服務(wù)的開發(fā)。
面向服務(wù)的架構(gòu) (SOA) 和面向服務(wù)的編程 是兩個術(shù)語,指軟件工程的風(fēng)格,它們將業(yè)務(wù)邏輯封裝為模塊化服務(wù)。這些服務(wù)以動態(tài)運行時環(huán)境為目標,在該環(huán)境中,服務(wù)提供者和服務(wù)消費者之間的關(guān)聯(lián)是松散 耦合的。松散耦合的服務(wù)通常沒有任何編譯時關(guān)聯(lián),所以在運行時,您可以動態(tài)地將它們鏈接在一起,并允許開發(fā)人員根據(jù)需要靈活地做出開發(fā)決策。除松散耦合之 外,下列概念也是面向服務(wù)的環(huán)境中的公共概念:
- 粗粒度:服務(wù)的粒度是指服務(wù)公開給出的功能范圍。細粒度的服務(wù) 表示定義一定程度的功能性的公共接口。粗粒度的服務(wù) 表示較一般程度的功能性,通常適合于給定的業(yè)務(wù)領(lǐng)域。
- 位置透明度 (Location transparency):位置透明度是指客戶機在不考慮位置的情況下訪問網(wǎng)絡(luò)上的服務(wù)。
- 協(xié)議獨立性:協(xié)議獨立性指客戶機在不考慮通信/網(wǎng)絡(luò)協(xié)議的情況下訪問服務(wù)。
將服務(wù)與這些概念綁定在一起是一項艱難的任務(wù)。但 POJO 編程可以簡化這一任務(wù)。
POJO 簡介
POJO 是無需遵循特定外部接口或第三方 API 的 Java 類。此功能本身就是取消代碼與外部關(guān)聯(lián)的耦合。去耦的主要好處之一是讓軟件開發(fā)人員無需開發(fā)輔助任務(wù)(如持久性、事務(wù)支持和遠程操作)。許多技術(shù)消除了組件/類的去耦,并促進了 POJO 編程,包括:
- 注釋是開發(fā)工具使用的、并用于生成代碼的元數(shù)據(jù),它可以 “裝飾” 一個類或部分類,以支持給定類型的功能或特性,如遠程操作、持久性和框架支持。
- 依賴性注入是構(gòu)建插入式 組件的技術(shù),對象創(chuàng)建和關(guān)聯(lián)是從組件移除的,并由容器或匯編組件實現(xiàn)。
- 反射是運行時發(fā)現(xiàn)的關(guān)于給定類或接口的信息,如方法、字段和構(gòu)造函數(shù)。
每種去耦技術(shù)都有其優(yōu)點和缺點。本文將通過 POJO 編程構(gòu)建一個簡單的 SOA 框架,它使用反射和 Geronimo 的 GBean 依賴性注入來讓組件去耦。
|
JMX 和 Geronimo
Geronimo 構(gòu)建在通用的內(nèi)核基礎(chǔ)上,它使用 Java Management Extensions (JMX) 和稱為 GBean 的托管組件的依賴性注入框架。實際上,Geronimo 中的每件事物(適配器、應(yīng)用程序和容器等)即是一個 GBean,也以 GBean 為基礎(chǔ)。GBean 與 JMX 和 JMX Managed Beans (MBeans) 共享許多相似點和相同的底層基礎(chǔ)設(shè)施。
|
Geronimo 的 GBean 框架
GBean 是 Geronimo 中的托管組件,這些組件共享許多相似點以及與 JMX MBean 的關(guān)系,如根據(jù)名為 GBeanInfo 的類公開屬性和操作,該類與 JMX 替代物 MBeanInfo 類非常相似。Geronimo 將 MX4J 庫(請參閱本文結(jié)尾的 參考資料)用作其 JMX 的實現(xiàn)。
GBean 維護狀態(tài)和關(guān)聯(lián)依賴性,并處理生命周期事件。GBean 可以注冊為其他 GBean 狀態(tài)中的相關(guān)方。啟動相關(guān) GBean 后,它將通過依賴性注入收到相關(guān) GBean 的引用。GBean 在任何給定的時間可以處于下列七個生命周期狀態(tài)之一:
清單 1 給出了一個包含一個屬性(消息)的簡單 GBean。
清單 1. 典型的 GBean
| public class TestGBean implements GBeanLifecycle { private static GBeanInfo GBEAN_INFO = null; static { GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(TestGBean.class); infoFactory.addAttribute("message", String.class, true); infoFactory.addOperation("getMessage"); GBEAN_INFO = infoFactory.getBeanInfo(); } private String message; public String getMessage() { return message; } ... } |
您可以使用 清單 2 中給出的代碼來啟動(激活)和停止 GBean。
清單 2. 啟動典型的 GBean
| ObjectName testGBeanOName = ObjectName.newInstance("jeffhanson.test:ID=test"); GBeanData gBeanData = new GBeanData(testGBeanOName, TestBean.GBEAN_INFO); gBeanData.setAttribute("message", "Hello world"); geronimoKernel.loadGBean(gBeanData, Thread.currentThread(). getContextClassLoader()); geronimoKernel.startGBean(testGBeanOName); ... geronimoKernel.stopGBean(testGBeanOName); geronimoKernel.unloadGBean(testGBeanOName); |
您可以在整個 Geronimo 內(nèi)核中大量地使用 GBean。
|
Geronimo 內(nèi)核
Geronimo 內(nèi)核 是 GBean 的一個框架。使用此框架,您可以建模并構(gòu)建任何復(fù) 雜的系統(tǒng)作為一組 GBean 容器和 GBean 組件,來管理狀態(tài)、關(guān)系和事件處理。
使用 KernelFactory 類,以編程方式創(chuàng)建 Geronimo 內(nèi)核是一個非常簡單的過程。清單 3 說明如何通過啟動內(nèi)核、記錄啟動時間和加載并啟動 servlet GBean 來創(chuàng)建名為 TestGeronimo 的新 Geronimo 內(nèi)核。
清單 3. 創(chuàng)建一個簡單的 Geronimo 內(nèi)核
| try { Kernel geronimoKernel = BasicKernelFactory.newInstance(). createKernel("TestGeronimo"); geronimoKernel.boot(); log.debug("Geronimo BootTime: " + geronimoKernel.getBootTime()); // add the servlet GBean ObjectName servletObjName = new ObjectName("jeffhanson.test:ID=MyGBean"); GBeanData servletGBeanData = new GBeanData(servletObjName, GBEAN_INFO); ClassLoader classLoader = getClass().getClassLoader(); geronimoKernel.loadGBean(servletGBeanData, classLoader); geronimoKernel.startGBean(servletObjName); } catch (Exception e) { log.error(e); } |
創(chuàng)建并運行內(nèi)核后,調(diào)用 POJO 服務(wù)上的方法就變成了練習(xí)使用 Geronimo 內(nèi)核服務(wù)器及其反射功能,如 清單 4 所示。
清單 4. 調(diào)用注冊到內(nèi)核的服務(wù)上的調(diào)用
| private static Object invokePOJOService(ObjectName serviceObjName, String operationName, String[] params) throws Exception { String[] paramTypes = null; if (params != null && params.length > 0) { paramTypes = new String[params.length]; for (int i = 0; i < params.length; i++) { paramTypes[i] = params[i].getClass().getName(); } } Kernel geronimoKernel = KernelManager.getInstance().getGeronimoKernel(); Object retVal = geronimoKernel.invoke(serviceObjName, operationName, (Object[])params, paramTypes); return retVal; } |
|
Geronimo 中面向服務(wù)的 POJO 的可適應(yīng)框架
本 文中引用的用于 SOA 的 POJO 框架使用 Geronimo 內(nèi)核實例將 POJO 注冊為 GBean,相關(guān)客戶機可以查詢并調(diào)用它們,而無需其他接口或 API。框架駐留在多層企業(yè)級應(yīng)用程序環(huán)境中的業(yè)務(wù)層中。服務(wù)定位符類負責與內(nèi)核交互,以查找并注冊(如果需要) 用作服務(wù)的 POJO。然后服務(wù)定位符類將 POJO 返回到調(diào)用它們的業(yè)務(wù)委派組件。圖 1 說明了框架中組件的關(guān)系。
圖 1. 用于 SOA 的 POJO 框架
該框架旨在從客戶機接收 HTTP 請求,然后將請求傳遞到調(diào)度程序組件,該組件會發(fā)送消息,并將請求分派給業(yè)務(wù)委派組件。 然后,業(yè)務(wù)委派組件使用服務(wù)定位符找到特定請求的服務(wù)。業(yè)務(wù)委派組件調(diào)用該服務(wù),并將任何返回值打包為模型對象。適當?shù)囊晥D組件將處理模型對象,并返回它作為對客戶機的格式化響應(yīng)。圖 2 中的順序圖說明了這些步驟。
圖 2. 典型 HTTP 請求和服務(wù)調(diào)用的往返順序
圖 3 中的類圖說明了框架的類之間的關(guān)系。
圖 3. 框架的類之間的關(guān)系
|
部署并運行框架
框架駐留在企業(yè)級應(yīng)用程序系統(tǒng)的業(yè)務(wù)層中。該框架公開一個接收 HTTP 請求的 servlet,并將內(nèi)容分派給框架進行處理。下一節(jié)將闡述簡單的部署過程。
部署框架
您可以將框架的類和企業(yè)級應(yīng)用程序打包在 .war 文件中,將其放置在 geronimo_home/deploy 目錄下。如果此目錄不存在,就創(chuàng)建它。
Geronimo 在啟動時會自動部署 .war 文件。放置在 deploy 目錄中的應(yīng)用程序是熱加載的,允許 Geronimo 在您做出更改時能夠在運行時重新加載應(yīng)用程序。這樣使調(diào)試應(yīng)用程序變得非常便利。
測試框架
您可以使用位于 geronimo_home/bin 目錄中的啟動腳本(startup.bat 或 startup.sh)啟動 Geronimo 應(yīng)用服務(wù)器。當調(diào)用 Geronimo 啟動腳本時,可以看到 Geronimo 控制臺窗口。部署框架和應(yīng)用程序后,啟動時的 Geronimo 控制臺窗口包含類似于 清單 5 所示的行,確認 Web 應(yīng)用程序已經(jīng)成功啟動。
清單 5. Web 應(yīng)用程序已經(jīng)成功啟動的確認
| 0 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel - Starting boot 422 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState - GBeanInstanceState for: :role=Kernel State changed from stopped to starting 422 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState - GBeanInstanceState for: :role=Kernel State changed from starting to running 422 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel - Booted 640 [main] DEBUG com.jeffhanson.apptier.FrontController - Geronimo BootTime: Sat May 20 18:51:08 MDT 2006 656 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState - GBeanInstanceState for: jeffhanson.test:ID=FrontController State changed from stopped to starting 656 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState - GBeanInstanceState for: jeffhanson.test:ID=FrontController State changed from starting to running |
現(xiàn)在,在 Web 瀏覽器窗口鍵入以下 URL,以激活 HelloWorld 服務(wù)上的 setMessage 操作:
http://:/?Action=HelloWorld&Operation=setMessage&Params=Hello+everybody!
當框架處理請求時,控制臺的輸出結(jié)果應(yīng)類似于 清單 6 所示。
清單 6. setMessage 操作處理的輸出結(jié)果
| 719 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator - Adding service [HelloWorld] to kernel... 719 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator - Loading GBean: jeffhanson.test:Name=HelloWorld,Type=GenericService 734 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState - GBeanInstanceState for: jeffhanson.test:Name=HelloWorld,Type=GenericService State changed from stopped to starting 734 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState - GBeanInstanceState for: jeffhanson.test:Name=HelloWorld,Type=GenericService State changed from starting to running |
在 Web 瀏覽器窗口中鍵入以下 URL,以激活 HelloWorld 服務(wù)上的 sayHello 操作:
http://:/?Action=HelloWorld&Operation=sayHello
當框架處理請求時,控制臺的輸出結(jié)果應(yīng)類似于 清單 7 所示。
清單 7. sayHello 操作處理的輸出結(jié)果
| 750 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator - serviceObjName: jeffhanson.test:Name=HelloWorld,Type=GenericService 750 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator - Service [HelloWorld] already in kernel 1156 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator - serviceObjName: jeffhanson.test:Name=HelloWorld,Type=GenericService 1156 [main] INFO com.jeffhanson.businesstier.services.HelloWorld - Hello everybody! |
當 servlet 引擎關(guān)閉 servlet,并調(diào)用 servlet 上的 destroy 方法時,servlet 會關(guān)閉 Geronimo 內(nèi)核。當 servlet 引擎關(guān)閉 servlet 時,您控制臺的輸出結(jié)果應(yīng)類似于 清單 8 所示。
清單 8. servlet 關(guān)閉后的輸出結(jié)果
| 1156 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel - Starting kernel shutdown 1156 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel - Kernel shutdown complete |
HelloWorld 類是帶有 setMessage 方法、getMessage 方法和 sayHelloWorld 消息的簡單 POJO。向 Geronimo 內(nèi)核注冊此類的實例后,您可以動態(tài)地調(diào)用該實例,并在運行時,使用依賴性注入將其與其他服務(wù)和組件關(guān)聯(lián)。清單 9 中的代碼說明了簡單的 HelloWorld POJO 類。
清單 9. 簡單的 HelloWorld 服務(wù)
| package com.jeffhanson.businesstier.services; import org.apache.log4j.Logger; public class HelloWorld { private static Logger log = Logger.getLogger(HelloWorld.class); private String message = "Hello world"; public void setMessage(String message) { if (message == null || message.length() <= 0) { throw new RuntimeException("HelloWorld.setMessage " + "param is not set"); } this.message = message; } public String getMessage() { return message; } public void sayHello() { log.info(message); } } |
|
結(jié)束語
設(shè) 計可以對業(yè)務(wù)更改和事件做出及時響應(yīng)的敏捷而又有效的 SOA 是一項復(fù)雜的任務(wù),但是,圍繞適當設(shè)計的 POJO 層構(gòu)建的 SOA 可以幫助簡化這一任務(wù)。Geronimo 平臺提供了框架和工具,您可以使用它通過 POJO 構(gòu)建靈活的、可擴展的和可維護的 SOA。
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/374079/viewspace-130287/,如需轉(zhuǎn)載,請注明出處,否則將追究法律責任。
轉(zhuǎn)載于:http://blog.itpub.net/374079/viewspace-130287/
總結(jié)
以上是生活随笔為你收集整理的[转载]使用 Apache Geronimo 和 POJO 构建 SOA 框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Openbravo开发手册
- 下一篇: 人脸识别-特征脸方法