基于Maven构建OSGI应用(Maven和OSGI结合)

基于Maven构建OSGI应用。

使用Maven来构建项目,包括项目的创建、子模块buldle的创建等。使用OSGI来实现动态模块化管理,实现模块的热插拔效果(即插即用)。

创建一个Maven项目:helloworld,并在该项目下创建两个Maven 子模块:helloworld-client、helloworld-server。

创建 helloworld maven项目、填写参数及Advanced Settings:

创建 helloworld-server maven子模块:

同样的方式再创建 helloworl-client maven 子模块。

接下来就是 hellworld-server、helloworld-client 编码以及OSGI及编译打包配置。

OSGI及编译打包配置,直接通过修改3个pom文件(1个主pom、2个子模块的pom)来配置,最终配置结果如下:

1)代码结构:

client->Activator.java:

package com.xxx.osgi.helloworld.client;import com.xxx.osgi.helloworld.server.HelloWorldImpl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;import java.util.Objects;/*** @author frank* @date 2023/12/8*/
public class Activator implements BundleActivator {public void start(BundleContext bundleContext) throws Exception {System.out.println("helloworld-client: start");System.out.println("helloworld-client: call server getHelloMsg()");ServiceReference<HelloWorldImpl> reference = bundleContext.getServiceReference(HelloWorldImpl.class);if (Objects.nonNull(reference)) {HelloWorldImpl service = bundleContext.getService(reference);if (Objects.nonNull(service)) {String msg = service.getHelloMsg("Frank");System.out.println("SUCCESS: return msg is:\n" + msg);} else {System.out.println("ERROR: service not found!");}bundleContext.ungetService(reference);} else {System.out.println("ERROR: service reference not found!");}}public void stop(BundleContext bundleContext) throws Exception {System.out.println("helloworld-client: stop");}
}

server->Activator.java

package com.xxx.osgi.helloworld.server;import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Objects;/*** @author frank* @date 2023/12/9*/
public class Activator implements BundleActivator {public void start(BundleContext bundleContext) throws Exception {System.out.println("helloworld-server: start");HelloWorldImpl server = new HelloWorldImpl();Dictionary<String, Object> properties = new Hashtable<String, Object>();bundleContext.registerService(HelloWorldImpl.class, server, properties);System.out.println("helloworld-server: 服务已发布(注册)!");}public void stop(BundleContext bundleContext) throws Exception {System.out.println("helloworld-server: stop");}
}

server->IHelloWorld.java

package com.xxx.osgi.helloworld.server;/*** @author frank* @date 2023/12/9*/
public interface IHelloWorld {String getHelloMsg(String name);
}

server->HelloWorldImpl.java

package com.xxx.osgi.helloworld.server;/*** @author frank* @date 2023/12/9*/
public class HelloWorldImpl implements IHelloWorld {public String getMethodName() {return "[" + Thread.currentThread().getStackTrace()[2].getMethodName() + ":" +Thread.currentThread().getStackTrace()[2].getLineNumber() + "] ";}public String getHelloMsg(String name) {return getMethodName() + " HelloWorld " + name;}
}

2)主pom:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.xxx.osgi</groupId><artifactId>helloworld</artifactId><version>1.0.0-SNAPSHOT</version><modules><module>helloworld-client</module><module>helloworld-server</module></modules><packaging>pom</packaging><name>helloworld</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>8</maven.compiler.source><parent.maven.bundle.plugin.version>2.4.0</parent.maven.bundle.plugin.version></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><!-- 该版本 maven 仓库找不到,如果要用该版本可以在 Project Structure->Project Settings->Modules 中设置:--><!-- 设置 OSGI:General->Configure OSGI Core Library->Use Library 指定本地 jar 文件静态添加 osgi lib  --><!--<groupId>org.eclipse</groupId><artifactId>osgi</artifactId><version>3.18.600.v20231110-1900</version><scope>provided</scope>--><!-- 该版本maven仓库可以找到,可以用这个版本。在 pom 中指定 osgi lib 的 dependency 依赖 --><groupId>org.eclipse</groupId><artifactId>osgi</artifactId><version>3.10.0-v20140606-1445</version><scope>provided</scope></dependency></dependencies>
</project>

3)hellworld-client 子模块pom:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>helloworld</artifactId><groupId>org.xxx.osgi</groupId><version>1.0.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>helloworld-client</artifactId><packaging>bundle</packaging><name>helloworld-client</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- osgi lib 使用主 pom 中定义的依赖,子模块不再重复定义 osgi lib dependency --><dependency><groupId>org.xxx.osgi</groupId><artifactId>helloworld-server</artifactId><version>${project.version}</version></dependency></dependencies><build><plugins><plugin><!-- osgi 打包配置,使用 maven-bundle-plugin 插件进行 osgi 打包 bundle jar --><!-- 使用maven-bundle-plugin打包方式时指定manifest文件不生效,但可在 instructions 中配置 manifest 参数 --><groupId>org.apache.felix</groupId><artifactId>maven-bundle-plugin</artifactId><version>${parent.maven.bundle.plugin.version}</version><extensions>true</extensions><configuration><instructions><!-- 如果要把依赖的 jar 也一起打包进去,在 Import-Package 中指定、并设置 Embed-Dependency --><!-- <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency> --><Bundle-Name>${project.name}</Bundle-Name><Bundle-SymbolicName>$(replace;${project.artifactId};-;_)</Bundle-SymbolicName><Bundle-Version>${project.version}</Bundle-Version><Bundle-Activator>com.xxx.osgi.helloworld.client.Activator</Bundle-Activator><Import-Package>org.osgi.framework,com.xxx.osgi.helloworld.server;version=${project.version}"</Import-Package><Export-Package>com.xxx.osgi.helloworld.client;version="${project.version}"</Export-Package></instructions></configuration></plugin></plugins></build>
</project>

4)helloworld-server 子模块pom:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>helloworld</artifactId><groupId>org.xxx.osgi</groupId><version>1.0.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>helloworld-server</artifactId><packaging>bundle</packaging><name>helloworld-server</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- osgi lib 使用主 pom 中定义的依赖,子模块不再重复定义 osgi lib dependency --></dependencies><build><plugins><plugin><!-- osgi 打包配置,使用 maven-bundle-plugin 插件进行 osgi 打包 bundle jar --><!-- 使用maven-bundle-plugin打包方式时指定manifest文件不生效,但可在 instructions 中配置 manifest 参数 --><groupId>org.apache.felix</groupId><artifactId>maven-bundle-plugin</artifactId><version>${parent.maven.bundle.plugin.version}</version><extensions>true</extensions><configuration><instructions><!-- 如果要把依赖的 jar 也一起打包进去,在 Import-Package 中指定、并设置 Embed-Dependency --><!-- <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency> --><Bundle-Name>${project.name}</Bundle-Name><Bundle-SymbolicName>$(replace;${project.artifactId};-;_)</Bundle-SymbolicName><Bundle-Version>${project.version}</Bundle-Version><Bundle-Activator>com.xxx.osgi.helloworld.server.Activator</Bundle-Activator><Import-Package>org.osgi.framework</Import-Package><Export-Package>com.xxx.osgi.helloworld.server;version="${project.version}"</Export-Package></instructions></configuration></plugin></plugins></build>
</project>

注意:

i)OSGI框架(OSGI Library)通过pom配置后自动manve刷新就可以自动在 Project Settings-> Modules 中自动生成 OSGI 配置了,包括OSGI Library也自设置了,这里无需手动修改其他OSGI配置,默认即可。根据pom自动生成的OSGI配置如下:

Configure OSGI Core Library 点击打开显示如下:

版本号就是pom中指定OSGI dependency 的版本。

ii)pom文件中配置打包插件使用:maven-bundle-plugin 插件,该插件是专门为OSGI打包提供的插件,但是它不能导出 META-INF 中的内容到 Export-Package jar 包中。也就是说使用 maven-bundle-plugin 插件打包导出的 bundle jar 包中的 manifest 只能通过 pom.xml 文件中的 maven-bundle-plugin 打包参数项来配置,不能直接指定使用自己项目中指定的 manifest 文件(指定了也不生效)。另外,Project Settings -> Modules 中的 Manifest Generation 配置也没有用。

另外,maven-bundle-plugin 打包插件支持了一个标签:
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>,
有了这个标签,可以直接把依赖的 jar 打入 bundle jar 包中去。注意:这种方式仅对第三方依赖(dependency)有效,例如 pom 中j加入 mysql-connector-java 驱动依赖:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version>
</dependency>

打包生成的bundle jar包中查看内容(jar tf xxx.jar),只要配置了 Embed-Dependency,对于 <dependency>定义的第三方依赖,都会打入目标bundle jar包中,直接把依赖的 mysql-connector-java-8.0.15.jar 文件导入进去了,位于根目录下:

但是,对于本地Lib库文件,例如下面这种依赖方式,Embed-Dependency 则无效,不会把 test-common-1.0.0.jar 打入bundle jar包中:

对于这种,可以使用另外一种方式,通过 Export-Package 导出。

还是用 mysql-connector-java 驱动来尝试,以本地Lib方式设置pom依赖(scope设置为system、并指定本地Lib文件路径),然后再设置 Export-Package 进行导出:

<Export-Package>com.xxx.osgi.helloworld.client;version="${project.version}",com.mysql.cj;version=8.0.32,com.mysql.jdbc;version=8.0.32
</Export-Package>

jar tf helloworld-client-1.0.0-SNAPSHOT.jar 查看bundle jar包结构如下:

 5)编译打包:

mvn clean package

执行命令,就会生成目标jar文件:

生成的jar内容结构查看,使用 jar tf jarFileName 命令查看:

e:\ws2\qf\helloworld\helloworld-client\target> jar tf helloworld-client-1.0.0-SNAPSHOT.jar

6)添加 debug / run 配置,可在idea中运行或调试:

为client和server分别添加一个 debug/run 配置,Bundle name配置中添加 4个 必须依赖的系统jar和各自子模块的jar:

添加 debug/run 配置并运行后,会自动生成  out 目录:

7)拷贝生成的 client & server bundle(jar) 到OSGI环境执行:

我本地Windows配置的OSGI运行环境位于:d:\osgi\equinox\

d:> cd d:\osgi\equinox\
d:\osgi\equinox> ls 
org.eclipse.osgi_3.18.600.v20231110-1900.jar
plugins
start.bat
d:\osgi\equinox> mkdir  my_bundles
d:\osgi\equinox> cp e:\ws2\qf\helloworld\helloworld-client\target\helloworld-client-1.0.0-SNAPSHOT.jar my_bundles\helloworld-client-1.0.0-SNAPSHOT.jar
d:\osgi\equinox> cp e:\ws2\qf\helloworld\helloworld-server\target\helloworld-server-1.0.0-SNAPSHOT.jar my_bundles\helloworld-server-1.0.0-SNAPSHOT.jar

8)执行bundles:

install & start bundles,server需要先启动、再启动client:

到此为止,基于Maven构建OSGI应用示例完毕。

注意:如果pom中指定<maven.compiler.source>8</maven.compiler.source>时编译报错:java: Compilation failed: internal java compiler error,报错截图如下:

检查下面几处相关设置是否正确:

1)检查File->Project Structure->Project Settings->Modules配置中的Dependencies->Module SDK

2)检查Settings->Buile,Execution,Deployment->Compiler->Java Compiler设置Module的Per-module bytecode version->Target bytecode version

如果 Per-module bytecode version -> Target bytecode version 不一致(我最初默认是1.5)、修改为一致(8),问题就解决了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/224153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

selenium/webdriver运行原理与机制

最近在看一些底层的东西。driver翻译过来是驱动&#xff0c;司机的意思。如果将webdriver比做成司机&#xff0c;竟然非常恰当。 我们可以把WebDriver驱动浏览器类比成出租车司机开出租车。在开出租车时有三个角色&#xff1a; 乘客&#xff1a;他/她告诉出租车司机去哪里&…

解决因找不到qt5core.dll文件而导致无法执行代码问题

Qt5core.dll是Qt5框架的核心模块&#xff0c;用于提供基本的Qt功能。如果在代码执行过程中找不到qt5core.dll&#xff0c;可能导致相关功能无法正常使用。以下是五种详细解决方法、qt5core.dll文件详细介绍以及丢失原因。 一、qt5core.dll文件详细介绍 文件名称&#xff1a;q…

vue文件下载请求blob文件流token失效的问题

页面停留很久token失效没有刷新页面&#xff0c;这时候点击下载依然可以导出文件&#xff0c;但是文件打不开且接口实际上返回的是401&#xff0c;这是因为文件下载的方式通过window创建a标签的形式打开的&#xff0c;并没有判断token失效问题 const res await this.$axios.…

10:00面试,10:08就出来了,问的问题超出我认知

本来在上家公司上班&#xff0c;加班是每天必不可少的&#xff0c;但是看在加班费给的比较多的份上&#xff0c;就没有太计较了。没想到9月份下一份通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降30%,这下搞的生活都生活不下去了。 还好有…

Dijkstra求最短路 I(Dijkstra算法)

给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权均为正值。 请你求出 1 号点到 n 号点的最短距离&#xff0c;如果无法从 1 号点走到 n 号点&#xff0c;则输出 −1。 输入格式 第一行包含整数 n 和 m。 接下来 m 行每行包含三个整…

python和pygame实现捉小兔游戏

python和pygame实现捉小兔游戏 python和pygame实现捉小兔游戏&#xff0c;需要安装使用第三方库pygame&#xff0c;关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 下面是使用Python和Pygame创建的游戏&#xff0c;其中有…

Pytorch从零开始实战13

Pytorch从零开始实战——ResNet与DenseNet探索 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——ResNet与DenseNet探索环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;P…

Java连接数据库实现用户登录和注册功能

目录 需求内容如下 示例代码 数据库studb Java代码 效果图 需求内容如下 1&#xff0c;创建数据库studb 2&#xff0c;库中添加用户表userinfo,包含如下字段 用户id ,用户名&#xff0c;用户密码&#xff0c;用户权限 &#xff08;数据类型和约束自己定义&#xff09…

web微服务规划

一、背景 通过微服务来搭建web系统&#xff0c;就要对微服务进行规划&#xff0c;包括服务的划分&#xff0c;每个服务和数据库的命名规则&#xff0c;服务用到的端口等。 二、微服务划分 1、根据业务进行拆分 如&#xff1a; 一个购物系统可以将微服务拆分为基础中心、会员…

SpringMVC异常处理机制

2.1 异常描述 在J2EE项目的开发中&#xff0c;不管是对底层的数据库操作过程&#xff0c;还是业务层的处理过程&#xff0c;还是控制层的处理过程&#xff0c;都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常&#xff0c;系统的代码耦合度高&a…

【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]

阅读导航 引言一、thread类的简单介绍二、线程函数详细介绍1. start() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型 2. join() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型 3. detach() 函数&#xff08;1&#xff09;头…

LeetCode Hot100 25.K个一组翻转链表

题目&#xff1a; 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯…

7+m6A+分型+实验,甲基化方向的生信思路,没有思路的同学可参考

今天给同学们分享一篇生信文章“Landscape analysis of m6A modification regulators related biological functions and immune characteristics in myasthenia gravis”&#xff0c;这篇文章发表在J Transl Med期刊上&#xff0c;影响因子为7.4。 结果解读&#xff1a; MG相…

快速文件搜索软件 Everything-voidtools

Everything 文件搜索软件 "Everything"是一款快速、轻巧且高效的桌面搜索引擎软件&#xff0c;专门用于在 Windows 操作系统上搜索文件和文件夹。它的主要特点是超快的搜索速度和精准的搜索结果&#xff0c;能够让用户快速找到他们需要的文件或文件夹。 1. 快速搜…

IDEA小技巧

目录 1. IDEA自动添加注释 创建类的时候自动添加注释 创建函数、方法的注释 1. IDEA自动添加注释 参考文档&#xff1a;idea java 自动添加文件注释 idea新建类自动注释_mob6454cc73c728的技术博客_51CTO博客 【操作工具】IDEA创建类及已有类添加注释-详细操作_idea设置创建…

搭建个人智能家居 开篇(搭建Home Assistant)

搭建个人智能家居 开篇&#xff08;搭建Home Assistant&#xff09; 前言Home Assistant搭建Home AssistantUbuntu系统搭建Windows系统搭建VM安装方法VirtualBox安装方法&#xff1a; 配置Home Assistant控制页面 前言 随着科技的进步、发展&#xff0c;物联网给我们的生活带来…

JdbcTemplate query系列方法指定jdbcType类型

使用SqlParameterValue类包装一下就行了&#xff0c;只要创建一个SqlParameterValue对象&#xff0c;通过构造函数把jdbcType类型&#xff08;用的是Types中的常量&#xff09;和值传入 例如&#xff1a; // 这两个包下面的 import org.springframework.jdbc.core.SqlParamete…

c YUV 转 JPEG(准备霍夫曼编码)

先取yuv 文件中一个168的块&#xff0c;跑通全流程 理解与思路&#xff1a; 1.块分割 YUV 文件分为&#xff1a;YUV444 YUV 422 YUV420。444:就是&#xff1a;12个char 有4个Y&#xff0c;4个U&#xff0c;4个 U&#xff0c;422&#xff1a;8个char 中有4个Y &#x…

Redis——01,服务器购买、安装Redis

服务器购买、安装Redis 一、随便去一个主流的国内主流的云服务提供商&#xff0c;购买一个服务器。二、Redis安装&#xff1a;————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶&#xffe3;)&#xff0c;谢…

[论文阅读]Multimodal Virtual Point 3D Detection

Multimodal Virtual Point 3D Detection 多模态虚拟点3D检测 论文网址&#xff1a;MVP 论文代码&#xff1a;MVP 论文简读 方法MVP方法的核心思想是将RGB图像中的2D检测结果转换为虚拟的3D点&#xff0c;并将这些虚拟点与原始的Lidar点云合并。具体步骤如下&#xff1a; (1)…