前言
在目前流行的java开发工具中,Eclipse和Idea都占有很大的市场份额。Eclipse 3.0以后的插件就是基于OSGI开发的,理论上使用Eclipse开发OSGI模块是最佳的选择。OSGI模块开发与普通的jar包开发最大的不同就是配置模块“元数据”, 而Eclipse中提供了可视化工具进行模块元数据配置。本人比较习惯使用Idea做java开发,本次demo讲解也是基于Idea开发工具进行。
OSGI模块是在OSGI框架中运行的,要搭建自己的开发环境首先就要选择一个OSGI框架,本示例选择的是Eclipse的equinox。关于如何在Idea开发工具中配置equinox,这里不进行讲解,可以参考http://blog.csdn.net/love_taylor/article/details/75194394 这篇文章。
示例讲解
本示例开发了4个Bundle模块:manager、server、client、api:
这4个模块的关系:
api模块的作用是定义服务接口,没有具体实现;
server模块实现了api中定义的接口,是具体的服务实现;
client模块作为服务使用方法,使用server模块提供的服务;
manager模块的作用仅仅是用来启动server和client模块,以及模拟定时启动或者停止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接口所在的包),但无需我们动手 Idea在Build 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
相关推荐
在这个"IntelliJ 13下OSGi的Maven例子"中,我们将会探索如何在IntelliJ IDEA 13中设置和运行一个基于OSGi的Maven项目。首先,我们需要了解OSGi的核心概念,如Bundle(模块)、Service、生命周期管理等。Bundle是OSGi...
**标题解析:** "blueprint-osgi-bundle:OSGi 示例" 指的是一个基于OSGi(Open Service Gateway Initiative)框架的示例项目,它使用了Blueprint服务容器来管理服务组件。Blueprint是Apache Felix项目中的一个子项目...
通常,一个OSGi示例项目会包含以下几个部分: 1. **配置文件**:如`config.ini`,这是OSGi框架启动时读取的配置文件,用于定义启动参数、服务设置等。 2. **Bundle(模块)**:在OSGi中,Java代码被打包成bundle,...
- **开发工具**: 使用 Eclipse 或 IntelliJ IDEA 的 OSGi 插件,如 PDE 或 Bndtools,可以方便地创建和管理 OSGi 捆绑。 - **打包和部署**: 将 Spring 应用转换为 OSGi 捆绑,可以使用 Maven 或 Gradle 的 OSGi ...
此外,Maven与Eclipse、IntelliJ IDEA等集成开发环境(IDE)具有很好的集成,进一步提高了开发效率。 最后,要确保在构建过程中识别和修复错误,上述内容中提到由于OCR扫描识别错误而产生了一些不完整或格式不正确...
jar,javadoc和源代码已发布到Maven Central Gradle构建(代码自动导入IDEA) OSGI清单条目 自动模块名称 用法 < groupId>com.github.vlsi.mxgraph</ groupId> < artifactId>jgraphx < version>4.2.2 文献...
7. `ide-plugins/` - 集成开发环境(IDE)的插件,如Eclipse或IntelliJ IDEA,方便在这些环境中开发OSGi应用。 8. `build-tools/` - 构建和打包工具,如Maven插件或Ant任务,用于构建OSGi bundle。 9. `README.md` ...
描述中提到的"基于Java的实例源码-懒惰者代码生成器 IdlerCodeGenerator.zip"与标题一致,强调这是一个包含源代码的实际示例。这意味着用户不仅可以使用这个工具,还能查看和学习其内部实现,这对于Java开发者来说是...
3. **代码集成与自动化**:利用 IntelliJ IDEA 的版本控制集成(如 Git)、构建工具集成(如 Maven 或 Gradle)以及自动化测试框架支持。 4. **Liferay 配置与调试**:设置 Liferay 服务器运行配置,进行远程调试,...
在Java生态系统中,插件主要用于提供可扩展性,常见的如Eclipse和IntelliJ IDEA等集成开发环境(IDE)中的插件,它们能够增强IDE的功能,例如代码自动完成、调试工具、版本控制集成等。此外,还有像Tomcat服务器中的...
- 设置IDE:使用Eclipse、IntelliJ IDEA或其他支持Maven的IDE。 - 配置Maven:确保Maven正确安装并配置到IDE中。 - 导入SDK:将SDK项目导入到IDE中,并确保正确配置了依赖关系。 ##### 2. 转换1.2版应用程序至...
要开始使用Apache Camel,你需要将这个包导入到你的开发环境中,如IDEA、Eclipse等,并根据项目需求配置相应的组件和路由规则。对于初学者,建议先阅读官方文档,了解基本概念和工作原理,然后通过简单的示例来实践...
此外,CXF还提供了一个强大的基于IDE的插件,如Eclipse或IntelliJ IDEA插件,帮助开发者更方便地使用CXF。 5. **安全机制**:CXF支持多种安全模型,包括基本认证、 Digest认证、SSL/TLS、WS-Security(Web Services...
对于学习和使用Kotlin,有多种资源可供参考,包括使用Gradle、Maven、Ant等构建工具的文档,以及Kotlin与OSGi的集成指南。IDE支持如IntelliJ IDEA Ultimate的Kotlin插件提供了强大的支持,包括对Spring等框架的特定...
- **Kotlin 与 OSGi**:Kotlin 在 OSGi 环境下的使用。 - **编译器插件**:自定义 Kotlin 编译器的行为。 - **常见问题解答 (FAQ)**:解决开发者在使用 Kotlin 过程中遇到的常见问题。 - **与 Java 比较**:Kotlin ...
标签中的“工具”可能指的是辅助开发插件系统的一些工具,如IDE插件(如Eclipse或IntelliJ IDEA的插件)、构建工具(如Maven或Gradle的插件系统)或特定的插件框架(如OSGi)。 综上所述,`JARCONNECTION`实现的...
Kotlin的协程支持有助于构建高度可伸缩的服务器端应用,并且与现有基于Java的技术栈完全兼容。 文档中还介绍了Kotlin的基本语法、编程习惯用法、编码规范、包的使用、控制流、函数和Lambda表达式、面向对象编程的类...
工具和生态系统方面,本教程介绍了如何使用Kapt、Gradle、Maven和Ant等构建工具,以及Kotlin与OSGi编译器插件的集成。编码规范部分提供了代码编写标准,以及Kotlin语言演进和不同组件稳定性演进的讨论。 本书是...