Maven构建OSGI+HttpServer应用

news2024/11/13 21:57:45

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 bundles
        ServiceReference 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 bundles
        httpService.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 bundles
            for (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 bundles
            for (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());

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("MyServlet return: Method=" + req.getMethod() + ", URI=" + req.getRequestURI());
    }

    @Override
    protected 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.coloradmin.cn/o/1436973.html

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

相关文章

jvm体系结构

一、Jvm 的介绍 1、JVM体系结构 2、JVM运行时数据区 3、JVM内存模型 JVM运行时内存 共享内存区 线程内存区 3.1、共享内存区 共享内存区 持久带(方法区 其他) 堆(Old Space Young Space(den S0 S1)) 持久代&#xff1a; JVM用持久带&#xff08;Permanent Space&…

MySQL数据库语句总结

一. 数据定义语言 DDL 数据定义语言&#xff0c;用来定义数据库对象的&#xff08;比如&#xff1a;数据库、表、字段等&#xff09; 1. 数据库操作 &#xff08;1&#xff09;查询所有的数据库 —— show databases; &#xff08;2&#xff09;创建数据库 —— create dat…

【数据结构】二叉树的顺序结构及实现(堆)

1.二叉树的顺序结构 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两…

架设游戏服务器租用价格?腾讯云和阿里云价格对比

游戏服务器租用多少钱一年&#xff1f;1个月游戏服务器费用多少&#xff1f;阿里云游戏服务器26元1个月、腾讯云游戏服务器32元&#xff0c;游戏服务器配置从4核16G、4核32G、8核32G、16核64G等配置可选&#xff0c;可以选择轻量应用服务器和云服务器&#xff0c;阿腾云atengyu…

蓝桥杯嵌入式学习记录——LCD的使用

目录 一、前言 二、LCD代码的移植 三、LCD代码的调用 一、前言 前一篇文章已经简单记录了一下cubeMX软件的使用和LED的点亮&#xff0c;今天来记录一下LCD的使用。LCD的驱动代码有很多&#xff0c;但实际上在蓝桥杯的比赛中用起来非常简单&#xff0c;因为赛点会提供LCD的驱…

nginx upstream server主动健康检测模块ngx_http_upstream_check_module 使用和源码分析(中)

目录 6. 源码分析6.1 解析指令分析6.2 待检查的服务器的添加和状态查询6.3 本模块的进程初始化函数6.4 准备执行健康检测任务6.5 执行健康检测任务本篇对ngx_http_upstream_check_module的源码实现进行详细分析。 关于配置和使用部分可以查看上篇:nginx upstream server主动健…

Layui 表格组件 头部工具栏 筛选列 加入全选和全不选的功能

Layui 表格组件 头部工具栏 筛选列 加入全选和全不选的功能 问题 前端使用Layui表格组件展示后台数据&#xff0c;因数据中涉及字段较多&#xff0c;因此加入了组件中固有的控制表格列隐藏显示的功能。奈何客户希望再此基础上&#xff0c;加入“全选”和“全不选”的功能&…

Github 2024-02-06 开源项目日报Top9

根据Github Trendings的统计&#xff0c;今日(2024-02-06统计)共有9个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目4TypeScript项目2C项目1Ruby项目1HTML项目1Go项目1Rust项目1C项目1Kotlin项目1 Magic Mask for And…

【golang】24、go get 和 go mod:indrect 与 go mod tidy

文章目录 go get 会执行如下操作&#xff1a; 操作 go.mod 文件&#xff08;add、update、remove&#xff09;下载依赖到 $GOPATH/pkg/mod 中若已安装&#xff0c;则更新该包&#xff0c;到最新版本 试验前置准备&#xff1a;首先删除已下载的依赖&#xff0c;rm -rf $GOPATH…

Linux虚拟文件系统(VFS)

虚拟地址空间通常是与进程密切相关的概念&#xff0c;而不是文件系统。虚拟地址空间是为了提供进程对内存的抽象和隔离而设计的。 文件系统不使用页表&#xff0c;直接使用物理地址。 虚拟文件系统是linux内核的一个核心子系统。、 虚拟文件系统的目的&#xff1a;通过一个抽…

基于CEVA DSP BX2的架构分析(六)-加载和存储单元(二)

6.4 指针修改机制 LS0和LS1都包含指针修改机制。当使用间接或索引寻址模式时&#xff0c;指针的修改可以与地址生成并行执行。在间接寻址模式中&#xff0c;指针包含地址&#xff0c;而在变址寻址模式下&#xff0c;指针包含偏移量&#xff08;有关这些寻址模式的更多详细信息&…

python实现飞书群机器人消息通知

python实现飞书群机器人消息通知&#xff08;消息卡片&#xff09; 直接上代码 """ 飞书群机器人发送通知 """ import time import urllib3 import datetimeurllib3.disable_warnings()class FlybookRobotAlert():def __init__(self):self.web…

数据库管理-第146期 最强Oracle监控EMCC深入使用-03(20240206)

数据库管理145期 2024-02-06 数据库管理-第146期 最强Oracle监控EMCC深入使用-03&#xff08;20240206&#xff09;1 概览2 性能中心3 性能中心-Exadata总结 数据库管理-第146期 最强Oracle监控EMCC深入使用-03&#xff08;20240206&#xff09; 作者&#xff1a;胖头鱼的鱼缸&…

【大数据】Flink on YARN,如何确定 TaskManager 数

Flink on YARN&#xff0c;如何确定 TaskManager 数 1.问题2.并行度&#xff08;Parallelism&#xff09;3.任务槽&#xff08;Task Slot&#xff09;4.确定 TaskManager 数 1.问题 在 Flink 1.5 Release Notes 中&#xff0c;有这样一段话&#xff0c;直接上截图。 这说明从 …

Stable Diffusion 模型下载:majicMIX realistic 麦橘写实 - V7

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 非常推荐的一个写实模型&#xff0c;由国人“Merjic”发布&#xff0c;下载量颇高。这款大模型带来非常高的写实度以及光影感&#xff0c;特别是光线在画面中生成的…

【JS逆向一】逆向某站的 加密参数算法--仅供学习参考

逆向日期&#xff1a;2024.02.06 使用工具&#xff1a;Node.js 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 可使用AES进行解密处理&#xff08;直接解密即可&#xff09;&#xff1a;在线AES加解密工具 1、打开某某网站(请使用文章开头的…

模拟串口LV2,解决硬件串口资源不足问题!!!!

模拟串口通信 2.0 版本&#xff01;&#xff01; 我在前面的文章里面有写了 虚拟串口通信&#xff0c;虽然说能用&#xff0c;但是用过的小伙伴都说 “好!” 优缺点: 先说一点&#xff0c;2.0版本并不适用于同硬件串口的所有场合&#xff0c;仅仅针对自己开发的电子垃圾的主…

用HTML5 + JavaScript实现下雪效果

用HTML5 JavaScript实现下雪效果 <canvas>是一个可以使用脚本 (通常为JavaScript) 来绘制图形的 HTML 元素。 <canvas> 标签/元素只是图形容器&#xff0c;必须使用脚本来绘制图形。 HTML5 canvas 图形标签基础https://blog.csdn.net/cnds123/article/details/…

架构(十三)动态本地锁

一、引言 加锁大家都知道&#xff0c;但是目前提供动态锁的基本都是分布式锁&#xff0c;根据订单或者某个收费款项进行加锁。比如这个1订单要收刷卡费用&#xff0c;那就OREDER_1做为key丢到redis进行分布式加锁。这也是当下分布式锁最流行的方式。 但是对于平台项目或者一些并…

飞天使-k8s知识点14-kubernetes散装知识点3-Service与Ingress服务发现控制器

文章目录 Service与Ingress服务发现控制器存储、配置与角色 Service与Ingress服务发现控制器 在 Kubernetes 中&#xff0c;Service 和 Ingress 是两种不同的资源类型&#xff0c;它们都用于处理网络流量&#xff0c;但用途和工作方式有所不同。Service 是 Kubernetes 中的一个…