`

基于idea+maven的OSGI示例

    博客分类:
  • OSGI
阅读更多

前言

 

在目前流行的java开发工具中,EclipseIdea都占有很大的市场份额。Eclipse 3.0以后的插件就是基于OSGI开发的,理论上使用Eclipse开发OSGI模块是最佳的选择。OSGI模块开发与普通的jar包开发最大的不同就是配置模块元数据, 而Eclipse中提供了可视化工具进行模块元数据配置。本人比较习惯使用Ideajava开发,本次demo讲解也是基于Idea开发工具进行。

 

OSGI模块是在OSGI框架中运行的,要搭建自己的开发环境首先就要选择一个OSGI框架,本示例选择的是Eclipseequinox。关于如何在Idea开发工具中配置equinox,这里不进行讲解,可以参考http://blog.csdn.net/love_taylor/article/details/75194394 这篇文章。

 

示例讲解

 

本示例开发了4Bundle模块:managerserverclientapi



 

4个模块的关系:

api模块的作用是定义服务接口,没有具体实现;

server模块实现了api中定义的接口,是具体的服务实现;

client模块作为服务使用方法,使用server模块提供的服务;

manager模块的作用仅仅是用来启动serverclient模块,以及模拟定时启动或者停止server模块,用于测试服务的消失和出现;

 

这个程序整体目的很简单,就是用于测试服务的是可以热插拔的。下面分别来看下各个模块的实现:

 

api模块

这个Bundle只定义了一个HelloService接口,由于这个模块不需要与OSGI框架交互,也不需要对外提供服务,所有不需要创建激活器。HelloService接口定义如下:

public interface HelloService {
    void sayHello();
}
 

 

元数据配置也很简单(这里没有使用Maven插件进行元数据配置),配置界面如下:



 

也许你会疑惑为什么不需要使用Export-Package导出包呢,否则其他模块不能通过Import-Package使用HelloService接口啊。这就是使用开发工具的好处,在同一个工程的多个模块中,Idea可以自动识别导入导出包,并自动添加到Bundle jar中(经过实验自动导入没有问题,导出有时候需要手动处理)。

 

server模块

该模块主要就是对api模块的接口进行实现,并注册一个服务到注册中心,即发布服务的过程。所以除了实现类以为,该模块还需要一个激活器 才能发布服务:

public class ServerAtivictor implements BundleActivator{
    private BundleContext context;
 
    @Override
    public void start(BundleContext context) throws Exception {
        this.context = context;
 
        //元数据,客户端在查询服务是可以根据元数据过滤
        Dictionary dictionary = new Properties();
        dictionary.put("test","test");
        //注册服务
        ServiceRegistration registration = context.registerService(HelloService.class.getName(),new HelloServiceImpl("小明"),dictionary);
        System.out.println("start server bundle");
 
    }
 
    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println("stop server bundle");
    }
}

实现类的内容很简单,就是打印一句话:

public class HelloServiceImpl implements HelloService {
 
    private String name;
 
    public HelloServiceImpl(String name) {
        this.name = name;
    }
 
    @Override
    public void sayHello() {
        System.out.println("Hello,"+name);
    }
}
 

 

再来看server模块的元数据配置,也很简单 比起api模块来说只是多了一个激活器配置:



 

理论上需要在Additional properties中添加Import-Package配置项 导入com.sky.osgi.api包(HelloService接口所在的包),但无需我们动手 IdeaBuild jar时会在元数据配置文件MANIFEST.MF中自动加入。最终server模块的元数据配置内容如下:

Manifest-Version: 1.0
Bnd-LastModified: 1516779536888
Bundle-Activator: com.sky.osgi.server.ServerAtivictor
Bundle-ManifestVersion: 2
Bundle-Name: com.sky.osgi.server
Bundle-SymbolicName: com.sky.osgi.server
Bundle-Version: 1.0.0
Created-By: 1.8.0_65 (Oracle Corporation)
Export-Package: com.sky.osgi.server;uses:="org.osgi.framework";version
 ="1.0.0"
Import-Package: com.sky.osgi.api,org.osgi.framework
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Tool: Bnd-3.3.0.201609221906
 

 

可见server模块自动导入了com.sky.osgi.api包和org.osgi.framework包(激活器在这个包中)。

 

client模块

该模块相比前两个模块稍微复杂些,主要作用是:模拟当server模块提供的服务可用时,使用该服务,当服务不可用时 提示服务不存在,但不影响client模块自己的业务运行。这里使用“服务追踪器”来感知服务的变化。首先看下激活器的实现内容:

public class ClientActivator implements BundleActivator {
 
    private ServiceTracker serviceTracker;
    private ExecutorService executorService;
 
    @Override
    public void start(BundleContext context) throws Exception {
        //创建一个带定制器的 追踪器
        serviceTracker = new ServiceTracker(context, HelloService.class.getName(), new MyServiceTrackerCustomizer(context));
        serviceTracker.open();//打开追踪器
 
        //新开一个线程,模拟调用服务
        executorService = Executors.newSingleThreadExecutor();
        executorService.submit(new TestTask(serviceTracker));
    }
 
    @Override
    public void stop(BundleContext context) throws Exception {
        serviceTracker.close();//关闭追踪器
        executorService.shutdown();
    }
}
 

 

再来看下模拟服务调用的任务类:

public class TestTask implements Runnable{
    public ServiceTracker serviceTracker;
 
    public TestTask(ServiceTracker serviceTracker) {
        this.serviceTracker = serviceTracker;
    }
 
    @Override
    public void run() {
            boolean flag = true;
            while (flag){
                try {
                    HelloService helloService = (HelloService)serviceTracker.getService();
                    if (helloService!= null) {
                        helloService.sayHello();
                    } else {
                        System.out.println("没有可用的服务");
                    }
                }catch (Exception e){
                    System.out.println("业务异常");
                }
 
                //睡5秒重试
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("线程池关闭");
                    flag = false;
                }
            }
    }
}

 

定制器MyServiceTrackerCustomizer的代码就不贴了,本文中所有的代码详见文章末尾提供的github地址。

 

由于idea自动配置导入导出,client模块的元数据配置界面也很简单:




manager模块

这个模块的作用很简单,就是控制server模块和client模块的启动和停止,该模块主要使用的是OSGI生命周期层的api。在OSGI框架启动是,把所有的4个模块加载到OSGI框架,并只启动manager模块,再由manager模块的激活器启动server模块和client模块。manager模块的激活器实现内容如下:

public class ManagerActivator implements BundleActivator{
    private Map<String,Bundle> bundleMap = new HashMap<>();
    private Thread thread;
 
    @Override
    public void start(BundleContext bundleContext) throws Exception {
        System.out.println("开始启动Bundle");
 
        //获取OSGI框架中已经所有Bundle
        Bundle[] bundles = bundleContext.getBundles();
        for (Bundle bundle:bundles){
            //启动server Bundle
            if(bundle.getSymbolicName().equals("com.sky.osgi.server")){
                bundle.start();
                bundleMap.put("com.sky.osgi.server",bundle);
            }
            //启动client Bundle
            if(bundle.getSymbolicName().equals("com.sky.osgi.client")){
                bundle.start();
                bundleMap.put("com.sky.osgi.client",bundle);
            }
            //为什么不启动api bundle呢?
            // 因为它不需要提供服务,也不需要与OSGI框架交互,只是作为导出api接口使用
        }
 
        System.out.println("所需Bundle启动结束");
 
        //启动线程修改server Bundle状态
        thread = new Thread(new UpdateTask());
        thread.start();
 
    }
 
    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        thread.interrupt();//停止线程
        bundleMap.clear();
    }
 
    class UpdateTask implements Runnable{
        @Override
        public void run() {
            Bundle server = bundleMap.get("com.sky.osgi.server");
            boolean flag = true;
            while(flag){
                try {
                    if (server.getState() != Bundle.ACTIVE){
                        server.start();
                    }else{
                        server.stop();
                    }
                } catch (BundleException e) {
                    e.printStackTrace();
                    System.out.println("Bundle启动停止出现异常");
                }
 
                try {
                    //模拟每隔10秒交替启动和停止Bundle
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    flag = false;
                    System.out.println("管理Bundle线程停止");
                }
            }
 
        }
    }
}
 

 

在该激活器中,创建了一个新的线程,模拟每隔10秒 启动或者停止server模块。client模块会自动感知服务的变化,并及时做出正确的相应,元数据配置方式以上面类似就不上图了。至此整个demo内容讲解完毕。

 

demo测试运行

如要正确的运行本示例代码,需要注意idea运行配置界面的配置:



 

注意“Start after insall”,意思是说框架加载模块完成后 就启动模块。这里只需要启动manager模块,在该模块中再来控制其他模块的启动。最后先build整个工程打包,点击运行或者debug运行,即可启动框架并执行整个工程代码。



 



 

 

测试结果表面 client模块可以实时的感知到server模块中服务的变化,并且彼此运行互不干扰,感兴趣的朋友可以自己运行试试。

 

总结

 

本次示例模拟内容虽然简单,但已经覆盖OSGI的模块层、生命周期层、服务层。这里再提下模块层元数据配置,本示例中主要使用的是idea自动的导入和导出机制。在开发一个大型的Bundle时,最繁琐的就是确定导入导出包,使用Idea开发工具可以减少这部分工作量。如果一定要手动配置元数据,可以使用Maven插件在pom.xml中配置:

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
                            <Bundle-Name>server</Bundle-Name>
                            <Bundle-SymbolicName>com.sky.osgi.server</Bundle-SymbolicName>
                            <Bundle-Version>1.0.0</Bundle-Version>
                            <Bundle-Vendor>sky</Bundle-Vendor>
                            <Bundle-Activator>com.sky.osgi.server.ServerAtivictor</Bundle-Activator>
                            <!--<Export-Package>-->
                                <!--com.sky.osgi.server-->
                            <!--</Export-Package>-->
                            <Import-Package>
                                org.osgi.framework
                            </Import-Package>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

 

可见manifestEntries节点里的配置项跟Bundle的元数据配置项是一一对应的。

 

 

另外本示例中,使用Maven引入包的方式和平时开发完全一样,就不再贴出pom.xml文件的配置内容,上述代码已上传GitHub: https://github.com/gantianxing/osgi_demo1.git

 

 

 

  • 大小: 21 KB
  • 大小: 26 KB
  • 大小: 54.6 KB
  • 大小: 67.1 KB
  • 大小: 48.6 KB
  • 大小: 15.6 KB
  • 大小: 8.8 KB
0
1
分享到:
评论

相关推荐

    Intellij 13下OSGi的Maven例子

    在这个"IntelliJ 13下OSGi的Maven例子"中,我们将会探索如何在IntelliJ IDEA 13中设置和运行一个基于OSGi的Maven项目。首先,我们需要了解OSGi的核心概念,如Bundle(模块)、Service、生命周期管理等。Bundle是OSGi...

    blueprint-osgi-bundle:OSGi 示例

    **标题解析:** "blueprint-osgi-bundle:OSGi 示例" 指的是一个基于OSGi(Open Service Gateway Initiative)框架的示例项目,它使用了Blueprint服务容器来管理服务组件。Blueprint是Apache Felix项目中的一个子项目...

    乱凑的一个osgi的demo

    通常,一个OSGi示例项目会包含以下几个部分: 1. **配置文件**:如`config.ini`,这是OSGi框架启动时读取的配置文件,用于定义启动参数、服务设置等。 2. **Bundle(模块)**:在OSGi中,Java代码被打包成bundle,...

    Spring OSGi 入门.pdf

    - **开发工具**: 使用 Eclipse 或 IntelliJ IDEA 的 OSGi 插件,如 PDE 或 Bndtools,可以方便地创建和管理 OSGi 捆绑。 - **打包和部署**: 将 Spring 应用转换为 OSGi 捆绑,可以使用 Maven 或 Gradle 的 OSGi ...

    构建工具:maven简介

    此外,Maven与Eclipse、IntelliJ IDEA等集成开发环境(IDE)具有很好的集成,进一步提高了开发效率。 最后,要确保在构建过程中识别和修复错误,上述内容中提到由于OCR扫描识别错误而产生了一些不完整或格式不正确...

    jgraphx-publish:将JGraphX发布到Maven Central

    jar,javadoc和源代码已发布到Maven Central Gradle构建(代码自动导入IDEA) OSGI清单条目 自动模块名称 用法 &lt; groupId&gt;com.github.vlsi.mxgraph&lt;/ groupId&gt; &lt; artifactId&gt;jgraphx &lt; version&gt;4.2.2 文献...

    Felix华为Felix开发和运行包。

    7. `ide-plugins/` - 集成开发环境(IDE)的插件,如Eclipse或IntelliJ IDEA,方便在这些环境中开发OSGi应用。 8. `build-tools/` - 构建和打包工具,如Maven插件或Ant任务,用于构建OSGi bundle。 9. `README.md` ...

    基于Java的实例源码-懒惰者代码生成器 IdlerCodeGenerator.zip

    描述中提到的"基于Java的实例源码-懒惰者代码生成器 IdlerCodeGenerator.zip"与标题一致,强调这是一个包含源代码的实际示例。这意味着用户不仅可以使用这个工具,还能查看和学习其内部实现,这对于Java开发者来说是...

    intellij-dev-life:为 dev.life 会话创建的示例存储库

    3. **代码集成与自动化**:利用 IntelliJ IDEA 的版本控制集成(如 Git)、构建工具集成(如 Maven 或 Gradle)以及自动化测试框架支持。 4. **Liferay 配置与调试**:设置 Liferay 服务器运行配置,进行远程调试,...

    java插件

    在Java生态系统中,插件主要用于提供可扩展性,常见的如Eclipse和IntelliJ IDEA等集成开发环境(IDE)中的插件,它们能够增强IDE的功能,例如代码自动完成、调试工具、版本控制集成等。此外,还有像Tomcat服务器中的...

    Rifidi Edge Server v1.3开发者文档

    - 设置IDE:使用Eclipse、IntelliJ IDEA或其他支持Maven的IDE。 - 配置Maven:确保Maven正确安装并配置到IDE中。 - 导入SDK:将SDK项目导入到IDE中,并确保正确配置了依赖关系。 ##### 2. 转换1.2版应用程序至...

    apache-camel-1.1.0.tar.gz

    要开始使用Apache Camel,你需要将这个包导入到你的开发环境中,如IDEA、Eclipse等,并根据项目需求配置相应的组件和路由规则。对于初学者,建议先阅读官方文档,了解基本概念和工作原理,然后通过简单的示例来实践...

    apache-cxf-2.6.2-src.zip

    此外,CXF还提供了一个强大的基于IDE的插件,如Eclipse或IntelliJ IDEA插件,帮助开发者更方便地使用CXF。 5. **安全机制**:CXF支持多种安全模型,包括基本认证、 Digest认证、SSL/TLS、WS-Security(Web Services...

    kotlin语法

    对于学习和使用Kotlin,有多种资源可供参考,包括使用Gradle、Maven、Ant等构建工具的文档,以及Kotlin与OSGi的集成指南。IDE支持如IntelliJ IDEA Ultimate的Kotlin插件提供了强大的支持,包括对Spring等框架的特定...

    kotlin语言基础教程.pdf

    - **Kotlin 与 OSGi**:Kotlin 在 OSGi 环境下的使用。 - **编译器插件**:自定义 Kotlin 编译器的行为。 - **常见问题解答 (FAQ)**:解决开发者在使用 Kotlin 过程中遇到的常见问题。 - **与 Java 比较**:Kotlin ...

    使用JARCONNECTION实现插件机制

    标签中的“工具”可能指的是辅助开发插件系统的一些工具,如IDE插件(如Eclipse或IntelliJ IDEA的插件)、构建工具(如Maven或Gradle的插件系统)或特定的插件框架(如OSGi)。 综上所述,`JARCONNECTION`实现的...

    kotlin文档

    Kotlin的协程支持有助于构建高度可伸缩的服务器端应用,并且与现有基于Java的技术栈完全兼容。 文档中还介绍了Kotlin的基本语法、编程习惯用法、编码规范、包的使用、控制流、函数和Lambda表达式、面向对象编程的类...

    kotlin中文教程

    工具和生态系统方面,本教程介绍了如何使用Kapt、Gradle、Maven和Ant等构建工具,以及Kotlin与OSGi编译器插件的集成。编码规范部分提供了代码编写标准,以及Kotlin语言演进和不同组件稳定性演进的讨论。 本书是...

Global site tag (gtag.js) - Google Analytics