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 開發(fā)基于 OSGi 的 Bundle 應(yīng)用

          開放服務(wù)網(wǎng)關(guān)協(xié)議 (Open Services Gateway Initiative),簡稱 OSGi,為網(wǎng)絡(luò)服務(wù)定義了一個(gè)標(biāo)準(zhǔn)的、面向服務(wù)的計(jì)算環(huán)境,為用戶提供了開放的、面向服務(wù)組件的、易于部署的編程模型,這個(gè)編程模型允許用戶將定義好的 接口規(guī)范綁定到 OSGi 運(yùn)行環(huán)境中的特定Service,在構(gòu)件 SOA 面向服務(wù)為中心的企業(yè)應(yīng)用的過程中,OSGi 技術(shù)正發(fā)揮越來越重要的作用。在本文中,將介紹 OSGi 的概念和體系結(jié)構(gòu),并且利用 Eclipse 3.2 開發(fā)一個(gè)基于 OSGi 規(guī)范的服務(wù)應(yīng)用 Bundle。通過學(xué)習(xí)本文,讀者可以了解到如何開發(fā)和部署基于 OSGi 規(guī)范的 Bundle 應(yīng)用。

          OSGi 規(guī)范簡介

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


          OSGi 體系結(jié)構(gòu)

          OSGi 的體系架構(gòu)是基于插件式的軟件結(jié)構(gòu),包括一個(gè) OSGi 框架和一系列插件,在 OSGi中,插件稱為 Bundle,其中,OSGi 框架規(guī)范是 OSGi 規(guī)范的核心部分,它提供了一個(gè)通用的、安全可管理的 Java 框架,通過這個(gè)框架,可以支持 Bundle 服務(wù)應(yīng)用的部署和擴(kuò)展。Bundle 之間可以通過 Import Package 和 Require-Bundle 來共享 Java 類,在 OSGi 服務(wù)平臺中,用戶通過開發(fā) Bundle 來提供需要的功能,這些 Bundle 可以動(dòng)態(tài)加載和卸載,或者根據(jù)需要遠(yuǎn)程下載和升級。OSGi 體系結(jié)構(gòu)圖如圖 1 所示:


          圖示1 OSGi 體系結(jié)構(gòu)
          圖示1 OSGi 體系結(jié)構(gòu)

          其中:

          Execution Environment:

          Bundle 應(yīng)用所倚賴運(yùn)行的 Java 執(zhí)行環(huán)境,如 J2SE-1.4、CDC-1.0 等都是可用的執(zhí)行環(huán)境。

          Modules:

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

          Life Cycle:

          生命周期層可以動(dòng)態(tài)地對 Bundle 進(jìn)行安裝、啟動(dòng)、停止、升級和卸載等操作。該層基于模塊層,提供了一組 API 來控制 Bundle 應(yīng)用的運(yùn)行時(shí)操作。

          Service Registry 和 Services:

          OSGi 服務(wù)層定義了一個(gè)集成在生命周期層中的動(dòng)態(tài)協(xié)作模型,是一個(gè)發(fā)布、動(dòng)態(tài)尋找、綁定的服務(wù)模型。一個(gè)服務(wù)通常是一個(gè) Java 對象實(shí)現(xiàn)了特定的服務(wù)接口,并且通過服務(wù)注冊,被綁定到 OSGi 的運(yùn)行環(huán)境中。Bundle 應(yīng)用可以注冊發(fā)布服務(wù),動(dòng)態(tài)綁定服務(wù),并且在服務(wù)注冊狀態(tài)改變時(shí),可以接受到事件消息等。

          Security:

          OSGi 的安全管理是基于 Java2 安全體系的,貫穿在 OSGi 平臺的所有層中,它能夠?qū)Σ渴鹪?OSGi 運(yùn)行環(huán)境中的 Bundle 應(yīng)用進(jìn)行詳細(xì)的管理控制。


          Bundle 生命周期的狀態(tài)

          在一個(gè)動(dòng)態(tài)擴(kuò)展的 OSGi 環(huán)境中,OSGi 框架管理 Bundle 的安裝和更新,同時(shí)也管理 Bundle 和服務(wù)之間的依賴關(guān)系。一個(gè) Bundle 可能處于以下六個(gè)狀態(tài),如圖 2 所示:


          圖示 2 Bundle 狀態(tài)圖
          圖示 2 Bundle 狀態(tài)圖

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

          RESOLVED:依賴關(guān)系滿足,這個(gè)狀態(tài)意味該Bundle要么已經(jīng)準(zhǔn)備好運(yùn)行,要么是被停止了。

          STARTING:Bundle正在被啟動(dòng),BundleActivator的start()方法已經(jīng)被調(diào)用但是還沒有返回。

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

          ACTIVE:Bundle 被成功啟動(dòng)并且在運(yùn)行。

          UNINSTALLED:bundle被卸載并且無法進(jìn)入其他狀態(tài)。

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


          OSGi 標(biāo)準(zhǔn)服務(wù)

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

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

          Start Level Service:Start Level是指一些在特定Bundle起動(dòng)之前必須運(yùn)行或者初始化的一系列 bundle。Start Lever Service 可以設(shè)置當(dāng)前OSGi服務(wù)框架初始的Start Level,并且可以指定和查詢特定Bundle的Start Level。



          使用 Eclipse 開發(fā) Bundle 應(yīng)用

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

          (1)創(chuàng)建 Plug-in Project,在 Eclipse 3.2 開發(fā)環(huán)境中,從菜單欄選擇 File > New > Project... ,打開 New Project 向?qū)В梢钥吹接蠵lug-in Project創(chuàng)建向?qū)В瑒?chuàng)建一個(gè)Plug-in 項(xiàng)目。項(xiàng)目名為 example 的 Bundle 應(yīng)用,該應(yīng)用實(shí)現(xiàn)并注冊了一個(gè)姓名查詢服務(wù),實(shí)現(xiàn)了 BundleActivator 接口。選擇 Equinox 框架作為 Bundle 應(yīng)用運(yùn)行的 OSGi 服務(wù)平臺。


          圖示 3 Plug-in 項(xiàng)目向?qū)?/strong>
          圖示 3 Plug-in 項(xiàng)目向?qū)? src=

          (2)實(shí)現(xiàn)OSGi服務(wù)通常需要兩個(gè)步驟,首先定義所提供服務(wù)的接口,然后實(shí)現(xiàn)這個(gè)服務(wù)接口。在本例中,我們創(chuàng)建一個(gè)姓名查詢服務(wù)用來查詢所給姓名是否有效。首先定義姓名查詢接口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);

          }


          該服務(wù)接口很簡單,只包含一個(gè)需要實(shí)現(xiàn)的方法。為了將服務(wù)接口和服務(wù)實(shí)現(xiàn)相分離,方便其他 Bundle 引用該服務(wù),我們通常需要將該服務(wù)接口單獨(dú)放在一個(gè)包內(nèi),本例中,存放NameService.java 接口的 Java 包為 example.service。接下來,需要實(shí)現(xiàn) NameService 接口,并且注冊該服務(wù)。在本例中,我們用內(nèi)部類實(shí)現(xiàn)了該接口,下面是該 Bundle 應(yīng)用的部分源代碼。


          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注冊一個(gè)姓名查詢服務(wù),并且為該服務(wù)設(shè)置相關(guān)屬性以便服務(wù)查詢。在實(shí)現(xiàn)姓名查詢服務(wù)時(shí),我們簡單定義了一個(gè)靜態(tài)數(shù)組用于存放有效的姓名信息。

          (3)定義Bundle描述文件MANIFEST.MF,Bundle應(yīng)用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屬性指明了實(shí)現(xiàn)BundleActivator接口的類,該類用來啟動(dòng)和停止Bundle應(yīng)用。Export-Package屬性指定了該Bundle輸出的共享包,該屬性可以使其他的Bundle應(yīng)用引用我們所定義的服務(wù)接口。

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


          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的部署及運(yùn)行

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

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


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

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


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

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


          圖示6 啟動(dòng)Bundle
          圖示6 啟動(dòng)Bundle

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


          總結(jié)

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



          下載





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

          導(dǎo)航

          統(tǒng)計(jì)

          • 隨筆 - 387
          • 文章 - 6
          • 評論 - 202
          • 引用 - 0

          常用鏈接

          留言簿(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

          • CROWD LDAP
          • Configuring+a+Delegated+Authentication+Directory
          • Membase NoSQL
          • Membase is a distributed key-value database management system

          Language

          • gosu-lang
          • Gosu is a programming language for the Java Virtual Machine (JVM).

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 557967
          • 排名 - 87

          最新評論

          閱讀排行榜

          評論排行榜

          free counters 主站蜘蛛池模板: 五家渠市| 师宗县| 皮山县| 宁远县| 凤城市| 永春县| 黄骅市| 巫溪县| 广丰县| 镇平县| 稷山县| 启东市| 泰安市| 湖南省| 延川县| 广西| 鄂伦春自治旗| 会同县| 沂源县| 光泽县| 寻乌县| 扬中市| 林西县| 台北县| 潞西市| 江永县| 霸州市| 绥阳县| 松江区| 青神县| 陈巴尔虎旗| 阜阳市| 延长县| 商都县| 兴业县| 邯郸县| 政和县| 建始县| 博湖县| 北宁市| 平遥县|