`
ssydxa219
  • 浏览: 610245 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

osgi 核心入门

    博客分类:
  • osgi
 
阅读更多

整理了一下,基本上的bundle还是那么几个:
   osgi 核心:
    org.eclipse.osgi_3.3.2
    org.eclipse.osgi.services_3.1.2
   equinox:
    org.eclipse.equinox.common_3.3.0
    org.eclipse.equinox.registry_3.3.1
    org.eclipse.equinox.http.jetty_1.0.1        (需要更新)
    org.eclipse.equinox.http.registry_1.0.1
    org.eclipse.equinox.http.servlet_1.0.1
    org.eclipse.equinox.preferences_3.2.1
    org.eclipse.equinox.log_1.0.1
    org.eclipse.equinox.preferences_3.2.1
必须的bundle:
    org.mortbay.jetty_5.1.11                (需要更新)
    javax.servlet_2.4.0                    (可选更新)
    org.apache.log4j_1.2.9
    org.apache.commons.logging_1.0.4
spring bundle:
    org.springframework.spring_2.5.2            (可选更新)   
    org.springframework.bundle.osgi.extender_1.0.2    (可选更新)
    org.springframework.bundle.osgi.core_1.0.2    (可选更新)
看了看一个基本的应用就需要这么多bundle,也够呛的,这还不算上hibernate,webwork,等其他第三方jar.

 

 

OSGi 入门

 

。Eclipse,反正搞java的基本都应该有了,这里用的是最近的3.4.1版本,以前一直用3.3.1,这两天刚更新。java就是这个比较讨厌,很多东西不停的更新,然后手上的工具包也得不停的更新。osgi 实现,当然首选equinox,版本也是3.4.1。其实Eclipse里面已经包括了equinox,当然单独下载也没有问题。看了看equinox,最近又增加了不少的服务,其实很多都是用不着的,别被这些东东吓着。
  简单的介绍一下需要的bundle:
  org.mortbay.jetty_5.1.14                 jetty 容器,当然是需要的,如果你不需要外部web服务器的话。
  org.eclipse.osgi_3.4.2.                这是核心的equinox实现,也就是系统bundle
  org.eclipse.osgi.services_3.1.2            这也是必备的,作为osgi服务接口
  org.eclipse.equinox.common_3.4.0            这也是必备的,equinox的共同核心
  org.eclipse.equinox.registry_3.4.0        这是用于equinox 插件扩展的,也是必须的。plugin.xml就是这个bundle处理的
  org.eclipse.equinox.http.servlet_1.0.1        http servlet包,包括了主要的proxyServlet类,作为主要的桥接Servlet
  org.eclipse.equinox.http.registry_1.0.1        http servlet,resource 注册服务
  org.eclipse.equinox.http.jetty_1.1.0        主要的用于启动jetty的代码
  javax.servlet_2.4.0                    servlet规范
  org.apache.commons.logging_1.0.4            用于处理日志
  以上的包都是必须的。
  其他可选的包,以后再介绍。
  好了,先在eclipse中建一个项目吧。创建plugin project而不是java project。当然你也可以转成pluign project。
  如以下的图,一直next
 


  提一下几个重要的文件:
  osgi bundles,必需的文件为MANIFEST.MF 大写,在META-INF下面
  plugin.xml,这是eclipse的插件文件,用于扩展使用。
  至于build.properties是用于打包的,可以不需要。
 
  修改一下相应的信息,如下图:基本上已经创建好了。
  
  简单说明一下:ID,也就是Bundle-SymbolicName 这是必须的。version 也就是Bundle-Version 也是必须的。其他可以随便。
 
  下面说明一下,我们需要几个重要的包,所以需要引入,点击Dependencies右边的import packages 的add。
  增加后,如下图
 
  说明一下,如果你需要引入相应的类,就像你在classpath中引入包一下一样。 
  由于,我们需要扩展Servlet,所以还需要http.servlets扩展,所以需要引入bundle:..http.registry。如下图:
 
  下面创建一个简单的HelloServlet
  public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.getWriter().print("My fist osgi application");
        resp.getWriter().close();
    }
}
 接下来是关键的一步,定义扩展
 如下图
 
 说明一下:class:org.demo.HelloServlet 就是我们创建的servlet
          alias:用于浏览器访问的路径,如http://localhost:8080/hello
 
 基本已经就绪,可以启动。
 创建一个新的osgi framework 运行配置,如下图:
 
 选择上面的几个bundle,以及你创建的项目。然后运行就可以了,默认的端口为80,如果需要更改,配置参数
 org.osgi.service.http.port=端口号
 如下图:
 
 现在可以直接在浏览器中访问了,一个osgi 应用已经完成。
 在console中输入ss,可以看到下面的提示,表示你的bundles基本已经运行正常。
 Framework is launched.
id    State       Bundle
0    ACTIVE      org.eclipse.osgi_3.4.2.R34x_v20080826-1230
1    ACTIVE      org.demo.helloworld_1.0.0
2    ACTIVE      org.eclipse.equinox.registry_3.4.0.v20080516-0950
3    ACTIVE      org.eclipse.osgi.services_3.1.200.v20071203
4    ACTIVE      javax.servlet_2.4.0.v200806031604
5    ACTIVE      org.eclipse.equinox.http.registry_1.0.100.v20080427-0830
6    ACTIVE      org.eclipse.equinox.http.jetty_1.1.0.v20080425
7    ACTIVE      org.eclipse.equinox.http.servlet_1.0.100.v20080427-0830
8    ACTIVE      org.eclipse.equinox.common_3.4.0.v20080421-2006
9    ACTIVE      org.mortbay.jetty_5.1.14.v200806031611
10    ACTIVE      org.apache.commons.logging_1.0.4.v20080605-1930

 

 

如何快速的开发一个osgi应用。下面来具体说明一下什么是osgi,以及osgi 能做什么,为什么使用osgi,以及到底osgi能带来什么益处。
    首先osgi是什么,osgi是由osgi alliance 制定的一个规范。由此规范,形成了osgi框架。基本上,osgi 也就是类似于servlet规范一样,提供相应的接口。而具体的实现,由相应的平台实现,如equinox平台。
    说了那么多,具体osgi能做什么呢?个人归纳了一下,包括以下几点:
    1.提供更高层次的模块管理,相对于java的包来说,osgi更加倾向于模块管理。
    2.提供更好的封装性,使用更加严格的类装载机制,让模块内的封装性变得更强。
    3.真正的面向接口,面向服务编程,使模块之间的耦合度大大降低。
    4.支持热部署,只要osgi内核运行着,其他模块可以随时更新,增加。
    5.易扩展,便于使用插件的模式进行扩展。具体看看eclipse的插件体系就知道了。
    简单介绍了一下osgi,下面说说osgi的几个层次:
    安全层:基于java2 安全机制,增加了相应的限制和使用标准的java 许可。
    模块层;定义标准的java 模型
    生命周期层:提供完整的bundles生命周期管理
    服务层:提供动态,简洁和持久化编程模型。
    相应的实际服务接口。
    主要来说说模块层,看过前面的例子应该知道,那个例子一共包括10个模块(包括系统模块)osgi 以bundle作为一个基本的模块单元。bundle主要包括需要的基础资源,包括类和其他资源文件;一个manifest文件,用于描述bundle信息,以及可选的osgi-opt目录。
    manifest文件是最重要的描述文件,如果缺失,则bundle也就无法装载。
    简单解释一下前面定义过的bundle manifest;bundle 文件包括几个必须的元素:
    Bundle-ManifestVersion: 2//定义了bundle遵循规范的规则,1表示r3规范 2表示r4和以后的版本
    Manifest-Version: 1.0 //主要的版本号
    //唯一的bundle名称,相当于在系统中的id。singleton表示是否使用单启动方式
    Bundle-SymbolicName: org.demo.helloworld;singleton:=true
    //以下是可选的
    Bundle-Name: Helloworld Plug-in//bundel 名称
    Bundle-Vendor: zsoft//发布商
    Bundle-RequiredExecutionEnvironment: J2SE-1.5//需要的执行环境
    //下面是一些引用包的信息,包括包名称和版本号,只有引用了这些包,才能让classloader装载。
    Import-Package: javax.servlet;version="2.4.0",
    javax.servlet.http;version="2.4.0",
    org.apache.commons.logging;version="1.0.4",
    org.osgi.framework;version="1.4.0"
   //这是直接引用整个bundle,一般不提倡整个引用,这里是用来定义扩展
   Require-Bundle: org.eclipse.equinox.http.registry;bundle-version="1.0.100"
   这里简单的描述了一下主要的几个bundle头信息,如果需要详细了解,具体参考相应的规范。本篇的内容就这些,下篇详细讲解一下osgi的类装载机制,

osgi一个最大的特色就是使用不同的ClassLoader,让多个bundle共享一个虚拟机,而每一个bundle使用单独的ClassLoader。
如下图所示:
 
对于资源和类的装载主要包括以下三种途径:
Boot classpath:启动类环境,包括java.*包和相应的实现包。
Framework classpath:osgi框架拥有一个独立的ClassLoader,用于装载框架接口类,以及相应的实现类。
Bundle Space:每个bundle包括了与bundle相关的jar文件,以及相关的资源。

对于一个类的查询,主要通过以下途径进行查询:
1.从Parent ClassLoader中装载
2.从Import Package中查询类路径。
3.从Required bundles中查询类
4.自身bundle,相关ClassPath
5.相关的插件片段Fragment。
如下图
 
这么说起来,还是比较的抽象,还是从一个实例来具体的分析。
假设有如下Bundle,
相关的描述文件如下:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->Bundle:org.zframework.core
Manifest
- Version:  1.0
Bundle
- Name: core
Bundle
- SymbolicName: org.zframework.core;singleton: = true
Bundle
- ClassPath: .
Import
- Package: net.sf.ehcache;version = " 1.3.0 " ,
 net.sf.ehcache.config;version
= " 1.3.0 " ,
 net.sf.ehcache.event;version
= " 1.3.0 " ,
 org.osgi.framework;version
= " 1.4.0 " ,
 org.osgi.service.log;version
= " 1.3.0 " ,
 
Require
- Bundle: org.eclipse.equinox.common;visibility: = reexport,
 
Export
- Package: org.zframework.core;version = " 1.0.0 " ,
 



现在创建了如下的类:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->package  org.zframework.core;
import  java.net.URL;
import  java.util.Collection;
import  net.sf.ehcache.Cache;
import  net.sf.ehcache.CacheManager;
import  net.sf.ehcache.Element;
import  org.osgi.framework.BundleContext;
public   class  EhCacheManager  extends  AbstractCacheManager  implements
    BundleContextAware {
    
private  String cacheFile;
    
private  BundleContext context;
    
private  CacheManager manager;
    
public  Cache getCache(String cacheName) {
    Cache cache 
=  manager.getCache(cacheName);
    
if  (cache  ==   null ) {
          
    }
    
return  cache;
    }
    
}


假设有一个Bundle org.zframework.model需要使用此类,描述如下:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->Manifest - Version:  1.0
Bundle
- Name: model
Bundle
- SymbolicName: org.zframework.model;singleton: = true
Bundle
- ClassPath: .
Import
- Package: javax.persistence;version = " 1.0.0 " ,
  javax.persistence.spi;version
= " 1.0.0 " ,
  org.osgi.framework;version
= " 1.4.0 " ,
  
 Require
- Bundle: org.zframework.core


类Model

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->package  org.zframework.model;
import  java.net.URL;
import  java.util.Collection;
import  org.zframework.core.EhCacheManager ;
public   class  Model{
    
private  EhCacheManager manager;
    
public  Object getCache(String key) {
    Object o 
=  manager.getCache(key);
    
return  o;
    }
    
}


下面简单说明一下装载过程:
在装载Model类时,
1.对于java.*类的装载,由相应的Boot ClassLoader 装载
2.装载EhCacheManager,
    1.在Import-Package中查询是否存在匹配中的org.zframework.core包声明,如果有,则委派给org.zframework.core包声明的Bundle进行装载,本例没有,则继续。
    2.在Require-Bundle中查询所有的Export声明包,判断是否存在org.zframework.core匹配。本例中,应该存在。如果不存在,则执行步骤2.3
    3.查询本bundle的类路径,是否有此类存在。不存在,继续2.4步骤
    4.查询所有的fragments bundle(特殊的bundle) 类路径。不存在,继续2.5步骤     
    5.判断是否使用DynamicImport-Package: * 声明,如果是则查询所有的bundle中声明的Export包。如果还是不存在,则抛出ClassNotFound例外。
关于DynamicImport-Package: * ,这是比较极端的设置,一般不会推荐使用,主要破坏了相关的封装性。
完整的类查询如下图:
 
关于类装载机制基本就是这些,对于初学者来说,这还是会有些困惑的。

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics