開發、構建並將 Java™ 類組件打包為開放服務網關協議(Open Services Gateway Initiative,OSGi)包,將其部署在 Apache Felix 運行時環境中。然後,使用 Felix Shell 命令啟動和停止包及對其進行動態更新。
引言
本文是本系列的第 1 部分,我們將開發包含客戶端和伺服器端組件的訂單應用程序。然後將這些組件打包為 OSGi 包。客戶端調用服務組件處理訂單。服務組件具有處理訂單和列印訂單 ID 的方法。閱讀本文後,您可以應用 Apache Felix 的概念和功能來將 Java 組件類構建和打包為 OSGi 包。
系統要求
要運行本文中的示例,請確保已在計算機上安裝和設置了以下軟體:
接下來,設置以下環境變數(按照示例 ANT_HOME=C:\apache-ant-1.7.0 進行設置):
接下來,將以下內容添加到 PATH 環境變數:
OSGi
OSGi 規範以更為動態的方式定義和傳播 Java 應用程序的模塊化。通常,Java 應用程序模塊化為 JAR 包。但是使用 JAR 文件有局限性:
為了處理上述問題,可以使用 OSGi 框架,因為其中對 Java 的模塊化系統進行了重新定義。相對於傳統的 JAR 模塊而言,基於 OSGi 的系統具有以下優勢:
目前有三個已知的 OSGi 實現:
本系列文章將介紹如何將 Felix 作為 OSGi 容器使用。本系列文章涵蓋以下主題:
訂單應用程序
接下來讓我們看看如何使用基於 Felix 的 OSGi 框架創建訂單應用程序包。此應用程序包括兩個組件:OrderClient.java(客戶端)和 OrderService.java(伺服器端)。客戶端組件打包為 client.jar,伺服器組件打包為 order.jar。接下來讓我們首先看看 OrderClient 類。
public class OrderClient implements BundleActivator { private ServiceTracker orderTracker; private OrderService orderService; public void setService(OrderService orderService) { this.orderService = orderService; } public void removeService() { this.orderService = null; } public void start(BundleContext context) throws Exception { orderTracker = new ServiceTracker(context, OrderService.class.getName(), null); orderTracker.open(); OrderService order = (OrderService) orderTracker.getService(); if (order == null) { System.out.println("Order service not available"); } else { order.processOrder(); } } public void stop(BundleContext context) { System.out.println("Bundle stopped"); orderTracker.close(); } } |
正如清單 1 中所示,OrderClient 對 OrderService 組件調用 processOrder 方法,以在啟動 client.jar 包時列印 orderID。此類實現 BundleActivator 介面,該介面具有兩個回調方法:start() 和 stop()。啟動和停止客戶端包時,Felix 容器將調用實現的 start() 和 stop() 方法。
接下來讓我們仔細分析一下 start() 方法。在 start() 方法中,首先獲得 ServiceTracker 類的引用。您可以將此類視為工廠類。然後通過調用此 getService 方法從此工廠類獲取服務引用。ServiceTracker 使用以下參數構造:包上下文和 OrderService 類的名稱。
public class OrderServiceImpl implements OrderService, BundleActivator { private ServiceRegistration registration; public void start(BundleContext context) { registration = context.registerService(OrderService.class.getName(), this, null); System.out.println("Order Service registered"); } public void stop(BundleContext context) { System.out.println("Order Service stopped"); } public void processOrder() { System.out.println("Order id: ORD123") ; } } |
伺服器端 order.jar 文件包含兩個組件:OrderService 介面和 OrderServiceImpl 類。此介面具有由 OrderServiceImpl 類實現的抽象類 processOrder。此類還實現了 BundleActivator 介面,此介面供 Felix 容器調用來啟動和停止 order.jar 包。start() 方法在註冊中心註冊 OrderService 組件,以供客戶端包使用。註冊與導出對象供其他包使用的作用一樣。
通過 Manifest 通信
真正的問題是,客戶端包如何知道註冊的服務包?此通信通過使用 Manifest 文件處理。在 Manifest 文件中,在導入和導出程序包中提供包的引用。客戶端包 Manifest 通常導入服務組件程序包,而服務包 Manifest 導出自己的程序包。請注意,當包 A 導入包 B 的程序包時,包 B 必須導出自己的程序包。沒有恰當的導入和導出定義,通信將失敗。
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Order Service Client Bundle-SymbolicName: orderclient Bundle-Version: 1.0.0 Bundle-Activator: order.client.OrderClient Import-Package: org.osgi.framework, org.osgi.util.tracker, order |
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Order Service Bundle-SymbolicName: orderservice Bundle-Version: 1.0.0 Export-Package: order Bundle-Activator: order.impl.OrderServiceImpl Import-Package: org.osgi.framework |
對於訂單應用程序,client.jar 包 Manifest 中包含條目 Import-Package: org.osgi.framework, org.osgi.util.tracker, order。這個實際上表示,客戶端包導入核心 OSGi 程序包和 OrderService 程序包。類似地,order.jar 包清單包含條目 Export-Package: order。即,包導出其程序包供客戶端使用。如果導入和導出未顯式聲明,OSGi 將引發運行時錯誤。
Manifest 文件還包含其他信息,如包激活器類的名稱等。激活器類負責在包中調用 start() 和 stop() 方法。在本例中,client.jar 包的激活器類為 OrderClient,order.jar 包的激活器類為 OrderService。
部署
在部署和使用包前,請進行以下工作:
下一步便是部署這些包。請通過以下步驟,使用 Felix OSGi 容器部署客戶端和服務包:
執行了上述構建文件后,將分別在 client/bin 和 service/bin 文件夾中創建 client.jar 和 order.jar 包。
每次啟動 Felix 運行時,都會提示配置文件名稱。配置文件名稱的作用類似於項目名稱。可以提供任何名稱作為項目配置文件的名稱。對於 Felix 運行時的每次後續啟動,如果提供了之前輸入的相同配置文件名稱,Felix 將會載入與該項目名稱關聯的所有已安裝包。如果提供了新配置名稱,則將需要再次顯式安裝各個包:
為了指示包的 ID,可以使用 ps 命令。必須首先啟動服務包,然後啟動客戶端包。在啟動相應的包時,將顯示以下輸出(請參見圖 2)。
還可以通過在 Felix Shell 提供 update bundle_id 命令更新包。包將在運行時動態更新。
結束語
本文簡單介紹了 OSGi 框架的功能和概念,並說明了如何使用其創建動態 JAR 包。您了解了如何構建並將組件打包為 OSGi 包,然後在 Felix 運行時環境中運行。我們還了解了如何創建包 Manifest 文件,以作為包之間的通信介面使用。
OSGi 提供了一種新的構建和管理 JAR 包的方式。請繼續關注本系列的第 2 部分,我們將介紹 Spring 框架在 OSGi 環境中如何代替 OSGi 承擔管理包的責任。(責任編輯:A6)
[火星人 ] OSGi 和 Spring,第 1 部分: 使用 Apache Felix 構建和部署 OSGi 包已經有908次圍觀