gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          利用 Eclipse 開發基于 OSGi 的 Bundle 應用

          開放服務網關協議 (Open Services Gateway Initiative),簡稱 OSGi,為網絡服務定義了一個標準的、面向服務的計算環境,為用戶提供了開放的、面向服務組件的、易于部署的編程模型,這個編程模型允許用戶將定義好的 接口規范綁定到 OSGi 運行環境中的特定Service,在構件 SOA 面向服務為中心的企業應用的過程中,OSGi 技術正發揮越來越重要的作用。在本文中,將介紹 OSGi 的概念和體系結構,并且利用 Eclipse 3.2 開發一個基于 OSGi 規范的服務應用 Bundle。通過學習本文,讀者可以了解到如何開發和部署基于 OSGi 規范的 Bundle 應用。

          OSGi 規范簡介

          OSGi 聯盟建立于 1999 年,是一個非贏利機構,旨在建立一個開放的服務規范。OSGi 規范為網絡服務定義了一個標準的、面向組件的計算環境,它最初的目的就是為各種嵌入式設備提供通用的軟件運行平臺,屏蔽設備操作系統與硬件區別的中間件平 臺,通過這個平臺,可以對不同軟件商提供的應用(OSGi 中稱為 Bundle)進行組件的生命周期管理的能力,如應用組件可以從運行中被安裝、升級或者移除而不需要中斷設備的操作,應用組件可以動態的發現和使用其他庫 或者應用程序。由于 OSGi 技術具有服務組件模塊化、動態加載應用等優點,正被越來越多的領域關注,如嵌入設備制造業、汽車制造業、企業應用等。目前,OSGi 聯盟發布的最新的 OSGi 服務規范為 4.0,讀者可以查閱參考資料了解詳細信息。


          OSGi 體系結構

          OSGi 的體系架構是基于插件式的軟件結構,包括一個 OSGi 框架和一系列插件,在 OSGi中,插件稱為 Bundle,其中,OSGi 框架規范是 OSGi 規范的核心部分,它提供了一個通用的、安全可管理的 Java 框架,通過這個框架,可以支持 Bundle 服務應用的部署和擴展。Bundle 之間可以通過 Import Package 和 Require-Bundle 來共享 Java 類,在 OSGi 服務平臺中,用戶通過開發 Bundle 來提供需要的功能,這些 Bundle 可以動態加載和卸載,或者根據需要遠程下載和升級。OSGi 體系結構圖如圖 1 所示:


          圖示1 OSGi 體系結構
          圖示1 OSGi 體系結構

          其中:

          Execution Environment:

          Bundle 應用所倚賴運行的 Java 執行環境,如 J2SE-1.4、CDC-1.0 等都是可用的執行環境。

          Modules:

          模塊層定義了 Bundle 應用的加載策略。OSGi 框架是一個健壯并且嚴格定義的類加載模型。在大多數 Java 應用中,通常只有一個單獨的 ClassPath,它包含了所有的 Java 類文件和資源文件,OSGi基于Java技術,對于每個實現了 BundleActivator 接口的 Bundle 應用,為它生成一個單獨的 ClassLoader,使得 Bundle 應用的組織更加模塊化。

          Life Cycle:

          生命周期層可以動態地對 Bundle 進行安裝、啟動、停止、升級和卸載等操作。該層基于模塊層,提供了一組 API 來控制 Bundle 應用的運行時操作。

          Service Registry 和 Services:

          OSGi 服務層定義了一個集成在生命周期層中的動態協作模型,是一個發布、動態尋找、綁定的服務模型。一個服務通常是一個 Java 對象實現了特定的服務接口,并且通過服務注冊,被綁定到 OSGi 的運行環境中。Bundle 應用可以注冊發布服務,動態綁定服務,并且在服務注冊狀態改變時,可以接受到事件消息等。

          Security:

          OSGi 的安全管理是基于 Java2 安全體系的,貫穿在 OSGi 平臺的所有層中,它能夠對部署在 OSGi 運行環境中的 Bundle 應用進行詳細的管理控制。


          Bundle 生命周期的狀態

          在一個動態擴展的 OSGi 環境中,OSGi 框架管理 Bundle 的安裝和更新,同時也管理 Bundle 和服務之間的依賴關系。一個 Bundle 可能處于以下六個狀態,如圖 2 所示:


          圖示 2 Bundle 狀態圖
          圖示 2 Bundle 狀態圖

          INSTALLED:安裝完成,本地資源成功加載。

          RESOLVED:依賴關系滿足,這個狀態意味該Bundle要么已經準備好運行,要么是被停止了。

          STARTING:Bundle正在被啟動,BundleActivator的start()方法已經被調用但是還沒有返回。

          STOPPING:Bundle正在被停止,BundleActivator的stop()方法已經被調用但是還沒有返回。

          ACTIVE:Bundle 被成功啟動并且在運行。

          UNINSTALLED:bundle被卸載并且無法進入其他狀態。

          Bundle接口定義了getState()方法來返回Bundle的狀態。


          OSGi 標準服務

          在 OSGi 平臺之上,OSGi 聯盟定義了很多服務。服務是由一個 Java Interface 來定義的,Bundle 可以實現這個接口并且把服務注冊到服務注冊表中去,用戶可以從注冊表中找到需要的服務來使用,并且可以響應特定服務的狀態改變,如服務注冊和服務取消。下 面簡單介紹一下 OSGi Release 4 的一些主要服務。OSGi 框架提供了權限管理服務,包管理服務和最初加載系統服務。這些服務是 OSGi 框架的一部分并且管理著 OSGi 框架的運作。

          Permission Admin Service:權限管理是指 Bundle 是否許可其他的 Bundle 的代碼。當前的或者其他的 Bundle 的權限可以通過這個服務來操作,一旦被設定權限,馬上就生效。 Package Admin Service:Bundle 之間可以共享包內的 Java 類和資源,bundle 的更新可能需要 OSGi 框架重新解析 Bundle 之間的依賴關系,這個服務提供了 OSGi 服務平臺中包的共享狀態信息。

          Start Level Service:Start Level是指一些在特定Bundle起動之前必須運行或者初始化的一系列 bundle。Start Lever Service 可以設置當前OSGi服務框架初始的Start Level,并且可以指定和查詢特定Bundle的Start Level。



          使用 Eclipse 開發 Bundle 應用

          Equinox 框架是 Eclipse 組織基于 OSGi Release 4 的一個實現框架,它實現了 OSGi 規范的核心框架和許多標準框架服務的實現。關于Equinox項目的詳細信息,請查閱參考資料信息。在本文中,我們使用 Eclipse 3.2 平臺開發兩個基于 OSGi 的 Bundle 應用,其中第一個 Bundle 應用聲明、實現并注冊了一個姓名查詢服務,用于判斷所給姓名是否在已定義的查詢列表中;第二個 Bundle 應用查詢并引用第一個 Bundle 應用所注冊的姓名查詢服務,如果用戶所給的姓名包含在查詢列表中,將返回正確的信息,最后,將開發的 Bundle應用部署的 Equinox OSGi 框架中,用戶可以在 OSGi 控制命令行中輸入命令來查詢關于框架和 Bundle 應用的具體信息。讀者可以從參考資料中獲得本文 Bundle 應用的源代碼。

          (1)創建 Plug-in Project,在 Eclipse 3.2 開發環境中,從菜單欄選擇 File > New > Project... ,打開 New Project 向導,可以看到有Plug-in Project創建向導,創建一個Plug-in 項目。項目名為 example 的 Bundle 應用,該應用實現并注冊了一個姓名查詢服務,實現了 BundleActivator 接口。選擇 Equinox 框架作為 Bundle 應用運行的 OSGi 服務平臺。


          圖示 3 Plug-in 項目向導
          圖示 3 Plug-in 項目向導

          (2)實現OSGi服務通常需要兩個步驟,首先定義所提供服務的接口,然后實現這個服務接口。在本例中,我們創建一個姓名查詢服務用來查詢所給姓名是否有效。首先定義姓名查詢接口NameService.java。下面是該接口的源代碼:


          NameService Interface 源代碼
          package example.service;

          /**

          * A simple service interface that defines a name service.

          * A name service simply verifies the existence of a Name.

          **/

          public interface NameService {

          /**

          * Check for the existence of a Name.

          * @param name the Name to be checked.

          * @return true if the Name is in the list,

          * false otherwise.

          **/

          public boolean checkName(String name);

          }


          該服務接口很簡單,只包含一個需要實現的方法。為了將服務接口和服務實現相分離,方便其他 Bundle 引用該服務,我們通常需要將該服務接口單獨放在一個包內,本例中,存放NameService.java 接口的 Java 包為 example.service。接下來,需要實現 NameService 接口,并且注冊該服務。在本例中,我們用內部類實現了該接口,下面是該 Bundle 應用的部分源代碼。


          Example Bundle部分源代碼
           public void start(BundleContext context) throws Exception {

          Properties props = new Properties();

          props.put("ClassRoom", "ClassOne");

          context.registerService(NameService.class.getName(), new NameImpl(),

          props);

          }

          private static class NameImpl implements NameService {

          // The set of names contained in the arrays.

          String[] m_name = { "Marry", "John", "David", "Rachel", "Ross" };

          /**

          * Implements NameService.checkName(). Determines if the passed name is

          * contained in the Array.

          *

          * @param name

          * the name to be checked.

          * @return true if the name is in the Array, false otherwise.

          */

          public boolean checkName(String name) {

          // This is very inefficient

          for (int i = 0; i < m_name.length; i++) {

          if (m_name[i].equals(name)) {

          return true;

          }

          }

          return false;

          }

          }


          在start()方法中,利用BundleContext注冊一個姓名查詢服務,并且為該服務設置相關屬性以便服務查詢。在實現姓名查詢服務時,我們簡單定義了一個靜態數組用于存放有效的姓名信息。

          (3)定義Bundle描述文件MANIFEST.MF,Bundle應用example的MANIFEST.MF文件如下:


          MANIFEST.MF文件信息
          Manifest-Version: 1.0

          Bundle-ManifestVersion: 2

          Bundle-Name: Example Bundle

          Bundle-SymbolicName: example

          Bundle-Version: 1.0.0

          Bundle-Activator: example.osgi.Activator

          Bundle-Localization: plugin

          Import-Package: org.osgi.framework;version="1.3.0"

          Export-Package: example.service


          其中,Bundle-Activator屬性指明了實現BundleActivator接口的類,該類用來啟動和停止Bundle應用。Export-Package屬性指定了該Bundle輸出的共享包,該屬性可以使其他的Bundle應用引用我們所定義的服務接口。

          (4)創建項目名為exampleClient的Bundle應用,該應用在OSGi平臺上查尋并引用example Bundle應用已經注冊的姓名查詢服務,然后從標準輸入讀入用戶所輸入的姓名信息,判斷所輸入姓名是否有效。exampleClient應用的部分源代 碼如下,讀者可從參考資料中獲得完整源代碼。


          ExampleClient Bundle部分源代碼
           public void start(BundleContext context) throws Exception {

          ServiceReference[] refs = context.getServiceReferences(

          NameService.class.getName(), "(ClassRoom=*)");

          if (refs != null) {

          try {

          System.out.println("Enter a blank line to exit.");

          BufferedReader in = new BufferedReader(new InputStreamReader(

          System.in));

          String name = "";

          // Loop endlessly.

          while (true) {

          // Ask the user to enter a name.

          System.out.print("Enter a Name: ");

          name = in.readLine();

          // If the user entered a blank line, then

          // exit the loop.

          if (name.length() == 0) {

          break;

          }

          // First, get a name service and then check

          // if the name is correct.

          NameService nameservice = (NameService) context

          .getService(refs[0]);

          if (nameservice.checkName(name)) {

          System.out.println("The Name is Correct.");

          } else {

          System.out.println("The Name is Incorrect.");

          }

          // Unget the name service.

          context.ungetService(refs[0]);

          }

          } catch (IOException ex) {

          }

          } else {

          System.out.println("Couldn't find any name service...");

          }

          }




          Bundle的部署及運行

          在Eclipse平臺中,選擇File-->Export...菜單,將開發的example和exampleClient兩個Bundle 應用導出成Jar文件,以便將它們部署到OSGi服務平臺中。選擇將要運行的Bundle應用,鼠標右鍵點擊,在彈出菜單中,選擇Run AS-->Equinox FrameWork來啟動OSGi服務平臺。在Equinox啟動配置控制臺中,可以為Bundle應用設置默認的Start Level和Bundle應用是否需要自動啟動等選項。在本例中,為了講解如何安裝及啟動Bundle應用,只將example Bundle應用設為自動啟動,而exampleClient Bundle應用需要我們用命令安裝及啟動。

          當OSGi Equinox FrameWork啟動后,在OSGi控制命令臺中輸入ss命令,可以查看OSGi服務平臺中已經安裝的Bundle應用信息及其狀態。如圖4所示,可以 看到當前OSGi服務平臺中有兩個Bundle處于Active狀態,其中,system.bundle_3.2.0.v20060328為OSGi框架 的系統Bundle,而example_1.0.0為注冊姓名查詢服務的Bundle應用,1.0.0為Bundle應用的版本號。


          圖示4 Bundle信息查詢
          圖示4 Bundle信息查詢

          在OSGi控制命令臺中利用install命令安裝exampleClient Bundle應用,用ss命令查看安裝后的Bundle應用信息及其狀態。如圖5所示:


          圖示5 安裝Bundle
          圖示5 安裝Bundle

          在OSGi控制命令臺中利用start命令安裝exampleClient Bundle應用,用戶可輸入姓名,利用姓名查詢服務來判斷所輸入姓名是否有效,用ss命令查看啟動后的Bundle應用信息及其狀態。如圖6所示:


          圖示6 啟動Bundle
          圖示6 啟動Bundle

          用戶在在OSGi控制命令臺中,可利用stop命令來停止指定的Bundle應用,close命令用來停止并退出OSGi控制命令臺。關于OSGi Equinox FrameWork控制臺命令的詳細信息,可查看參考資料。


          總結

          OSGi服務框架提供了開放的、面向服務的、易于部署的編程模型,在構件面向服務為中心的企業應用的過程中,OSGi 技術正發揮越來越重要的作用。目前,Eclipse 3.2 體系架構是參照OSGi實現的,Equinox框架是 Eclipse 組織基于OSGi Release 4 的一個實現框架,它實現了OSGi 規范的核心框架和許多標準框架服務。在本文中,我們利用Eclipse 平臺開發了兩個Bundle應用,并且在Bundle應用中,聲明、實現、注冊并引用了一個簡單的服務,最后,將Bundle應用部署到Equinox OSGi服務框架中。通過本文,讀者可以了解如何開發和部署基于OSGi規范的Bundle應用。



          下載





          posted on 2008-05-08 10:50 gembin 閱讀(1088) 評論(0)  編輯  收藏 所屬分類: OSGi

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          free counters
          主站蜘蛛池模板: 玉田县| 萨迦县| 沈阳市| 内乡县| 揭西县| 安远县| 孙吴县| 安顺市| 永安市| 皮山县| 山西省| 府谷县| 南康市| 宜阳县| 昭苏县| 河津市| 额济纳旗| 松滋市| 栾川县| 巴东县| 临武县| 祁东县| 巩义市| 临澧县| 阿尔山市| 阜平县| 昭苏县| 大竹县| 涟源市| 大兴区| 大英县| 孟州市| 新源县| 东乡县| 巴马| 隆昌县| 和田市| 瑞金市| 湄潭县| 于田县| 石柱|