Maven构建OSGI+HttpServer应用

Maven构建OSGI+HttpServer应用

官网(https://eclipse.dev/equinox/server/http_in_equinox.php)介绍有两种方式:

一种是基于”org.eclipse.equinox.http”包的轻量级实现,另一种是基于”org.eclipse.equinox.http.jetty”包(基于jetty的Servlet)实现。

使用 "org.eclipse.equinox.http" 包(例如:http-1.0.100-v20070423.jar),可以将我们自定义的服务(servlet或静态资源页面)注册到这个 HttpService 中去,实现自定义的HTTP服务。

"org.osgi.service.http" 包(例如:org.osgi.service.http-1.2.2.jar)内部会内嵌一个 HttpService Interface,而"org.eclipse.equinox.http" 包(http-1.0.100-v20070423.jar)提供了一个上述Interface的 HttpService实现类,因此,一旦这个osgi bundle (http-1.0.100-v20070423.jar)启动了,就会有一个内嵌的 http 服务被启动,默认地址是 http://localhost,端口为 80,可以通过指定参数 “org.osgi.service.http.port”来修改默认端口。

"org.eclipse.equinox.http" 包(http-1.0.100-v20070423.jar)内有一个上面那个 HttpService Interface 的实现类:

想要提供我们自定义的 HttpService服务,就要将我们的服务(servlet或静态资源页面)注册到这个 HttpService 中去,需要用到 "org.osgi.service.http" 包中的 HttpService 类的两个注册方法:

1)注册静态资源:
registerResources(String alias, String name, HttpContext httpContext)

2)注册 Servlet 类:
registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext httpContext)

所以要想提供我自己的WebService实现,我们就需要:

提供自定义的WebService实现的步骤如下:
1)获取 httpService 对象;
2)编码提供 servlet 和 webpage 的实现;
3)将 servlet 和 webpage 注册到 HttpService 服务中去(同时指定对应的 alias);
4)访问;

新建manve项目:

创建package、class、和编码:
1)Java package:com.xxx.osgi.httpserver.demo、com.xxx.osgi.httpserver.servlet
2)Java class文件:Activator.java、MyServlet.java

Activator.java:

package com.xxx.osgi.httpserver.demo;import com.xxx.osgi.httpserver.servlet.MyServlet;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;import java.util.LinkedList;
import java.util.List;/*** @author Frank* @date 2023/12/26*/
public class Activator implements BundleActivator {private static BundleContext bundleContext;private HttpService httpService;private List<Bundle> bundles;static BundleContext getBundleContext() {return bundleContext;}public void start(BundleContext bundleContext) throws Exception {Activator.bundleContext = bundleContext;installBundles(bundleContext, false); // install other bundlesServiceReference serviceReference = bundleContext.getServiceReference(HttpService.class.getName());httpService = (HttpService) bundleContext.getService(serviceReference);// 注册HttpContext httpContext = httpService.createDefaultHttpContext();// 注册静态页面,设置别名"/osgi",所有对"/osgi"的请求映射到"/webpage/index.html"httpService.registerResources("/osgi", "/webpage/index.html", httpContext);System.out.println("start ok");// 注册 servlet,设置servlet别名"/test",所有对'/test"的请求映射到myServlet的实现MyServlet myServlet = new MyServlet();httpService.registerServlet("/test", myServlet, null, httpContext);}public void stop(BundleContext bundleContext) throws Exception {installBundles(bundleContext, true); //uninstall other bundleshttpService.unregister("/osgi");httpService.unregister("/test");Activator.bundleContext = null;System.out.println("stop ok");}public void installBundles(BundleContext context, boolean uninstall) {List<String> bundleFiles = new LinkedList<String>();List<Bundle> installedBundles = new LinkedList<Bundle>();//install my other bundles// System.out.printf("1 %s\n", FileLocator.getBundleFile(FrameworkUtil.getBundle(Activator.class)).getAbsolutePath());// System.out.printf("2 %s\n", FileLocator.getBundleFile(context.getBundle()).getAbsolutePath());// System.out.printf("3 %s\n", context.getBundle().getLocation());// String baseDir = FileLocator.getBundleFile(context.getBundle()).getParentFile().getAbsolutePath();String baseDir = context.getBundle().getLocation().replaceFirst("/[^/]*.jar","/");bundleFiles.add(baseDir + "helloworld-server-1.0.0-SNAPSHOT.jar");if (!uninstall) {// install & start bundlesfor (String bundleFile : bundleFiles) {try {Bundle bundle = context.installBundle(bundleFile);installedBundles.add(bundle);bundle.start();} catch (BundleException e) {if (!e.getMessage().contains("A bundle is already installed")) {throw new RuntimeException(e);}}}bundles = installedBundles;System.out.printf("all bundles (cnt = %d) installed and started!", bundles.size());} else {// stop & uninstall bundlesfor (Bundle bundle : bundles) {try {context.getBundle(bundle.getBundleId()).stop();context.getBundle(bundle.getBundleId()).uninstall();} catch (BundleException e) {throw new RuntimeException(e);}}System.out.printf("all bundles (cnt = %d) stopped and uninstalled!", bundles.size());}}
}

MyServlet.java:

package com.xxx.osgi.httpserver.servlet;import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.logging.Logger;public class MyServlet extends HttpServlet implements Servlet {private Logger logger = Logger.getLogger(this.getClass().getName());@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("MyServlet return: Method=" + req.getMethod() + ", URI=" + req.getRequestURI());}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("MyServlet return: Method=" + req.getMethod() + ", URI=" + req.getRequestURI());}
}

3)创建静态页面文件:webpage/index.html

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>jetty test</title>
</head>
<body>
<h2>OSGI HttpServer/Jetty Test</h2>
<font color="green"> register static resource/pages: </font><br>
registerResources(String alias, String name, HttpContext httpContext) <br><br><font color="green">register servlet class: </font><br>
registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext httpContext)
</body>
</html>

4)创建&编辑 pom.xml 文件

pom文件中定义了OSGI框架和版本、编码中所需的依赖以及osgi menifest和osgi打包配置:

<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>com.xxx.osgi</groupId><artifactId>osgi-httpserver-demo</artifactId><version>1.0.0-SNAPSHOT</version><packaging>bundle</packaging><name>osgi-httpserver-demo</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><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><!-- START: httpServer required bundles --><!-- org.osgi.service.cm_1.6.1.202109301733.jar --><dependency><groupId>org.osgi</groupId><artifactId>org.osgi.service.cm</artifactId><version>1.6.1</version></dependency><!-- javax.servlet-3.0.0.v201112011016.jar --><dependency><groupId>org.eclipse.jetty.orbit</groupId><artifactId>javax.servlet</artifactId><version>3.0.0.v201112011016</version></dependency><!-- http-1.0.100-v20070423.jar --><dependency><groupId>org.eclipse.equinox</groupId><artifactId>http</artifactId><version>1.0.100-v20070423</version></dependency><!-- org.osgi.service.http-1.2.2.jar --><dependency><groupId>org.osgi</groupId><artifactId>org.osgi.service.http</artifactId><version>1.2.2</version></dependency><!-- END: httpServer required bundles --><!-- for: org.eclipse.core.runtime.FileLocator --><!-- common-3.6.200-v20130402-1505.jar / org.eclipse.equinox.common.source_3.18.200.v20231106-1826.jar --><dependency><groupId>org.eclipse.equinox</groupId><artifactId>common</artifactId><version>3.6.200-v20130402-1505</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>3.5.0</version><extensions>true</extensions><configuration><instructions><!-- 把依赖的普通jar和bundle jar也一起打包进去(/lib目录下),bundle jar 服务依赖还要在 Import-Package 中指定 --><Embed-Dependency>*;scope=compile|runtime</Embed-Dependency><Embed-Directory>lib</Embed-Directory><Embed-Transitive>true</Embed-Transitive><!-- BEGIN: 把本地静态资源目录也打包进去 --><Include-Resource>webpage=webpage</Include-Resource><!-- END: 把本地静态资源目录webpage也打包进去(到webpage目录、相当于目录拷贝) --><Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath><Bundle-Name>${project.name}</Bundle-Name><Bundle-SymbolicName>$(replace;${project.artifactId};-;_)</Bundle-SymbolicName><Bundle-Version>${project.version}</Bundle-Version><Bundle-Activator>com.xxx.osgi.httpserver.demo.Activator</Bundle-Activator><DynamicImport-Package>*</DynamicImport-Package><Import-Package>javax.servlet,javax.servlet.http,org.osgi.service.http;resolution:="optional"</Import-Package><Export-Package></Export-Package></instructions></configuration></plugin></plugins></build>
</project>

整体项目的代码结构如下:

准备运行依赖的bundles:

org.osgi.service.cm_1.6.1.202109301733.jar
javax.servlet-3.0.0.v201112011016.jar
org.osgi.service.http-1.2.2.jar
http-1.0.100-v20070423.jar
 

直接在 configuration/config.ini 初始化启动配置中加入依赖 bundles 或者启动 osgi 以后执行 install 安装依赖 bundles:
install plugins/org.osgi.service.cm_1.6.1.202109301733.jar
install other_bundles/javax.servlet-3.0.0.v201112011016.jar
install other_bundles/org.osgi.service.http-1.2.2.jar
install other_bundles/http-1.0.100-v20070423.jar
start 5 6 7 8 

注意,多条命名install时有先后顺序依赖,也可以放在一条命令执行多个 bundle 的install(无顺序依赖)
install plugins/org.osgi.service.cm_1.6.1.202109301733.jar other_bundles/javax.servlet-3.0.0.v201112011016.jar other_bundles/org.osgi.service.http-1.2.2.jar other_bundles/http-1.0.100-v20070423.jar
 

“org.osgi.service.http”的HttpService Interface的实现类bundle “org.eclipse.equinox.http”启动后,HttpService服务就启动了、查看HttpService监听端口已开启(如果equinox的配置文件或启动参数没有指定 org.osgi.service.http.port=8080 的话,默认是监听的是 80 端口):

项目编译打包:
执行命令打包
mvn clean package

拷贝项目编译打包生成的jar文件到osgi运行环境:

执行osgi-httpserver-demo jar包(install & start):

项目bundle 9已经启动、bundle9内代码install & start 的其他bundel 10 也都start成功,状态为ACTIVE了。

httpServer 访问测试(访问 localhost:8080/osgi 和 localhost:8080/test):
命令行访问页面:

浏览器访问页面:

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

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

相关文章

『 C++ - STL 』unordered_xxx系列关联式容器及其封装(万字)

文章目录 &#x1f3a1; unordered系列关联式容器&#x1f3a1; 哈希表的改造&#x1f3a2; 节点的设置与总体框架&#x1f3a2; 迭代器的封装&#x1f3a0; 迭代器的框架&#x1f3a0; operator()运算符重载&#x1f3a0; 其余成员函数/运算符重载 &#x1f3a2; 迭代器begin(…

ORM模型类

模型 创建两个表 创建模型类 from django.db import models# Create your models here. class BookInfo(models.Model):name models.CharField(max_length10, uniqueTrue) # 书名pub_date models.DateField(nullTrue) # 发布时间read_count models.IntegerField(default…

【TCP/IP】用户访问一个购物网站时TCP/IP五层参考模型中每一层的功能

当用户访问一个购物网站时&#xff0c;网络上的每一层都会涉及不同的协议&#xff0c;具体网络模型如下图所示。 以下是每个网络层及其相关的协议示例&#xff1a; 物理层&#xff1a;负责将比特流传输到物理媒介上&#xff0c;例如电缆或无线信号。所以在物理层&#xff0c;可…

ElastAlert 错误日志告警

文章目录 前言一、ElastAlert 概览1.1 简介1.2 ElastAlert 特性 二、ElastAlert 下载部署2.1 安装 Python3 环境2.2 下载 ElastAlert2.3 部署 ElastAlert 三、接入平台3.1 对外接口层3.2 服务层 前言 ElastAlert 是 Yelp 公司基于 python 开发的 ELK 日志告警插件&#xff0c;…

vue electron应用调exe程序

描述 用Python写了一个本地服务编译成exe程序&#xff0c;在electron程序启动后&#xff0c;自动执行exe程序 实现 1. 使用node的child_process模块可以执行windows执行&#xff0c;通过指令调exe程序 // electron/index.js var cp require("child_process"); /…

C++泛编程(3)

类模板基础 1.类模板的基本概念2.类模板的分文件编写3.类模板的嵌套 在往节内容中&#xff0c;我们详细介绍了函数模板&#xff0c;这节开始我们就来聊一聊类模板。C中&#xff0c;类的细节远比函数多&#xff0c;所以这个专题也会更复杂。 1.类模板的基本概念 和函数模板一样…

AES算法:数据传输的安全保障

在当今数字化时代&#xff0c;数据安全成为了一个非常重要的问题。随着互联网的普及和信息技术的发展&#xff0c;我们需要一种可靠的加密算法来保护我们的敏感数据。Advanced Encryption Standard&#xff08;AES&#xff09;算法应运而生。本文将介绍AES算法的优缺点、解决了…

【调试】pstore原理和使用方法总结

什么是pstore pstore最初是用于系统发生oops或panic时&#xff0c;自动保存内核log buffer中的日志。不过在当前内核版本中&#xff0c;其已经支持了更多的功能&#xff0c;如保存console日志、ftrace消息和用户空间日志。同时&#xff0c;它还支持将这些消息保存在不同的存储…

H5 简约四色新科技风引导页源码

H5 简约四色新科技风引导页源码 源码介绍&#xff1a;一款四色切换自适应现代科技风动态背景的引导页源码&#xff0c;源码有主站按钮&#xff0c;分站按钮2个&#xff0c;QQ联系站长按钮一个。 下载地址&#xff1a; https://www.changyouzuhao.cn/11990.html

适合龙年春节的SVG模版

宝藏模版 往期推荐&#xff08;点击阅读&#xff09;&#xff1a; 趣味效果&#xff5c;高大上&#xff5c;可爱风&#xff5c;年终总结&#xff08;一&#xff09;&#xff5c;年终总结&#xff08;二&#xff09;&#xff5c;循环特效&#xff5c;情人节&#xff08;一&…

Quartus IP 之mif与hex文件创建与使用

一、mif与hex概述 ROM IP的数据需要满足断电不丢失的要求&#xff0c;ROM IP数据的文件格式一般有三种文件格式&#xff1a;.mif、.hex、.coe&#xff0c;Xilinx与Intel Altera支持的ROM IP数据文件格式如下&#xff1a; Xilinx与Altera支持的ROM文件格式 Alterahex、mifAM&am…

DolphinScheduler本地安装

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

如果品牌刚刚开始,切入私域社群团购,快团团是最好的选择

如果品牌刚刚开始&#xff0c;切入私域社群团购&#xff0c;快团团是最好的选择&#xff0c;借力新渠道社群团购&#xff0c;快团团&#xff0c;成就你的新品牌&#xff0c; 社群团购平台本身就有大量的信任你平台的流量&#xff0c;这个流量基数是巨大的。 你要知道的是&…

惟客数据地产经营分析解决方案-构建数字化经营体系,提高精细化管理能力

惟客数据地产经营分析解决方案以拉通数据底座&#xff0c;以管理行为、量化考核、预警机制为核心&#xff0c;强化对经营风险的识别和解决&#xff0c;以终为始&#xff0c;通过高频高价值场景的应用适配&#xff0c;支撑企业在数字化时代中不断创新、转型&#xff0c;提升企业…

Rhino.Inside带材质将Revit模型bake到Rhino

Hello大家好&#xff01;我是九哥~ 今天来讲一个小技巧&#xff0c;就是我通常采用RIR将Revit的模型的Geometry Bake到Rhino&#xff0c;肯定是没有材质的&#xff0c;那么如果我们需要带材质那要怎么办呢&#xff1f; 对于会的人&#xff0c;其实挺简单的&#xff0c;只需要…

力扣热门100题 - 4.寻找两个正序数组的中位数

力扣热门100题 - 4.寻找两个正序数组的中位数 题目描述&#xff1a;示例&#xff1a;提示&#xff1a;解题思路&#xff1a;代码&#xff1a; 题目链接&#xff1a;4.寻找两个正序数组的中位数 题目描述&#xff1a; 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&a…

用python编写爬虫,爬取房产信息

题目 报告要求 工程报告链接放在这里 https://download.csdn.net/download/Samature/88816284使用 1.安装jupyter notebook 2.用jupyter notebook打开工程里的ipynb文件&#xff0c;再run all就行 注意事项 可能遇到的bug 暂无&#xff0c;有的话私信我

Verilog刷题笔记20

题目&#xff1a; Case statements in Verilog are nearly equivalent to a sequence of if-elseif-else that compares one expression to a list of others. Its syntax and functionality differs from the switch statement in C. 解题&#xff1a; module top_module ( …

docker自定义镜像并使用

写在前面 本文看下如何自定义镜像。 ik包从这里 下载。 1&#xff1a;自定义带有ik的es镜像 先看下目录结构&#xff1a; /opt/program/mychinese [rootlocalhost mychinese]# ll total 16 -rw-r--r-- 1 root root 1153 Feb 5 04:18 docker-compose.yaml -rw-rw-r-- 1 el…

C语言中的内存函数你知道多少呢?

目录 ​编辑 1. memcpy的使用和模拟实现 1.1函数介绍 ​编辑 1.2函数的使用 1.3模拟实现 2. memmove的使用和模拟实现 2.1函数介绍 2.2函数的使用 2.3模拟实现 3. memset函数的使用 3.1函数介绍 3.2函数的使用 ​编辑 4. memcmp函数的使用 4.1函数介绍 4.2函数…