Karaf教程之Config Admin服务的使用_configurationadmin-程序员宅基地

技术标签: osgi  OSGi  Karaf  

目录

摘要
配置管理服务规范
如何使配置生效
引入简单的可配置类
动手实践。使用OSGi接口方式实现配置
例子运行
深入Karaf配置命令
使用Blueprint配置
部署配置文件
总结和展望未来
参考文献

摘要

在Karaf教程的第一部分,我们学习了如何使用maven和blueprint提供和使用pojo服务,以及如何使用http服务发布一个servlet。
在第二部分,我们关注OSGi bundles的配置。和servlet容器不同,对于配置OSGi包含了一个非常好的规范:来自OSGi企业规范的配置管理服务。在该教程中,将涉及分别通过OSGi和blueprint方式来使用配置管理服务,以及如何使配置文件和bundles自动化部署。

教程的代码可以在github查阅,地址Here

配置管理服务规范

首先我们看下配置服务规范概览。这里使用到主要有以下两个接口:

  • ConfigurationAdmin -允许检索和改变配置。这个服务是配置管理服务实现提供的接口。

  • ManagedService -配置发生改变的时候,允许做出响应。你不得不实现这个接口,并且把它注册为一个服务来获取通告。

所以基本上在配置管理服务中的配置是一个字典,这个字典包含了属性和相应的值。字典被一个持久化标识符(persistent identifier (pid))标识.标识是一个简单的字符串,且唯一的标识该配置。

如何使配置生效

可以通过使用ConfigurationAdmin.getConfiguration接口检索一个配置,但不推荐这么做。OSGi是动态的以至于可能发生这样的情况,bundles在config admin服务或者config admin服务还没有读取配置之前启动了。所以有时可能获取到一个null配置。

因此推荐的方式是使用ManagedService服务来监听更新。如果因为没有配置bundle不能启动,则可在第一次更新消息被接收的时,通过创建一个可配置的pojo对象是一个不错的主意。

引入简单的可配置类

按照需求,可配置的类应该是pojo。虽然可以简单地实现ManagedService接口并直接使用Dictionary,这需要依赖于OSGi和当前的Config Admin Service规范。因此改用一个具有title属性的简单bean类。另外添加了一个刷新方法,在配置项被更改之后应该被调用。

public class MyApp {

  String title;

  public void setTitle(String title) {
    this.title = title;
  }

  public void refresh() {
    System.out.println("Configuration updated (title=" + title + ")");
  }
}

我们的目的是配置tilte,当配置改变的时候要调用refresh方法。我们将使用OSGi方式和blueprint两种方式实现。

动手实践。使用OSGi接口方式实现配置

首先在本节展示通过使用OSGi接口如何使用config admin服务。然而这绝不可能是你以后要这么实现。这仅仅是帮助你理解在钩子下发生了什么。
你可以在这个子目录下configapp找到实现(https://github.com/cschneider/Karaf-Tutorial/tree/master/configadmin/configapp)
首先我们需要一个pom文件用于maven编译。你最好从例子中configapp的pom开始看起。
如果你才刚开始,你将不得不使用maven-bundle-plugin编译你的工程为一个OSGi bundle,且你需要添加两个依赖:

<dependency>
  <groupId>org.osgi</groupId>
  <artifactId>org.osgi.compendium</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>org.osgi</groupId>
  <artifactId>org.osgi.core</artifactId>
  <version>4.2.0</version>
</dependency>

第一个依赖是用于config admin服务相关接口,第二个依赖是用于创建Activator和包含基本的OSGi相关的接口。

现在我们将专注修订MyApp类。下面的类达到了目的。我们实现了ManagedService接口用于和Config Admin服务交互。无论什么时候配置发生变化,ConfigUpdater都被调用。
第一件事是检查是否为null,这个情况是可能发生的,当config被移除的时候。关于这个步骤我们可以停掉MyApp运行,但是为了保持简单我们仅仅是忽略了这些问题。下一步是创建一个MyApp实例。
正常情况,你将在Activator完成这个步骤,但是你将不得不考虑空配置的情况,这种情况不是我们期望的。最后一步是简单地从config获取一个值传入setter方法并调用,且在设置完所有配置后调用refresh方法。

private final class ConfigUpdater implements ManagedService {
    

  public void updated(Dictionary config) throws ConfigurationException {
    if (config == null) {
      return;
    }

    if (app == null) {
      app = new MyApp();
    }

    app.setTitle((String)config.get("title"));
    app.refresh();
  }
}

当然这样还没有完成所有事情,最后一步是在Activator.start注册ConfigUpdater。类似其他服务一样我们简单地使用了registerService。唯一特别的事情是你不得不设置属性SERVICE_PID到你的配置pid,这样Config Admin服务就知道你想要监听的是什么配置了。

Hashtable<String, Object> properties = new Hashtable<String, Object>();
properties.put(Constants.SERVICE_PID, CONFIG_PID);
serviceReg = context.registerService(ManagedService.class.getName(), new ConfigUpdater() , properties);

例子运行

  • 运行mvn install编译工程.
  • 启动一个新的Karaf实例
  • 从target目录复制configapp.jar bundle到Karaf deploy目录

现在我们注意到好像什么事都没发生。在Karaf控制台调用list你应该能够看到bundle实际上是已经启动,但是却没有任何输出,因为没有配置。我们仍然需要创建配置文件和设置tilte。
- 复制已经存在的文件/configadmin-features/src/main/resources/ConfigApp.cfg 到Karaf实例中的/etc目录

这里重要的部分是文件名必须是.cfg。这样config admin服务能够发现它。

现在fileinstall bundle将在etc目录下侦测到新的文件。当以.cfg结尾的文件将被当作配置管理资源且根据文件名pid来创建或者更新对应的Config Admin服务配置。

所以现在你应该在Karaf控制台能看到如下输出。这显示了配置的变化被检测和转发。如果你现在用编辑器修改文件内容和保存修改,修改将被通告。

Configuration updated (title=" + title + ")

深入Karaf配置命令

在Karaf控制台输入如下:

> config:list
Pid:            ConfigApp
BundleLocation: file:/C:/java/apache-karaf-2.2.3/deploy/configapp.jar
Properties:
   service.pid = ConfigApp
   felix.fileinstall.filename = file:/C:/java/apache-karaf-2.2.3/etc/ConfigApp.cfg
   title = my Title

在配置列表中你应该能够找到配置ConfigApp。这个配置显示配置文件从哪里加载的,pid标识符和在文件中设置的所有属性。

我们也可以修改配置:

> config:edit ConfigApp
> config:propset title "A better title"
> config:proplist
   service.pid = ConfigApp
   felix.fileinstall.filename = file:/C:/java/apache-karaf-2.2.3/etc/ConfigApp.cfg
   title = A better title
> config:update
Configuration updated (title=A better title)

我们发现修订直接通告到bundle,如果你查看etc下配置文件,你可以发现修订也被持久化到文件了。所以在重启Karaf后修订仍然生效。

使用Blueprint配置

继我们用OSGi实现和Config Admin服务交互后,现在我们将看下使用Blueprint怎么实现相同的功能。幸运地是这种方式十分的简单,Blueprint做了大部分的事情。

简单的定义一个cm:property-placeholder元素。类似文件中的属性占位符但是这个是和Config Admin服务起作用。我们需要提供config PID和更新策略。当我们选择reload策略,这意味着一个修订发生,blueprint的上下文环境会重新加载反映这个修订。当config PID没有找到或者属性不存在,将设置为默认属性值。

和bean类集成通常是一个简单的bean定义,这个bean是定义了title属性和分配了一个占位符。通过使用config admin服务解析这个占位符。唯一特别是的事情是init-method。
这被用于在配置修订后,我们机会去做相应的事情。例如上面的OSGi例子。

因为blueprint我们不需要任何maven依赖,因此java代码仅是一个Java bean时。通过把它放在OSGI-INF/blueprintblueprint目录和blueprint extender被加载,环境很容易被激活。因为在Karaf中blueprint总是被加载,所以我们不需要做其他事情。

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
[http://www.osgi.org/xmlns/blueprint/v1.0.0] [http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd]
[http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0] [http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd]
">
<cm:property-placeholder persistent-id="ConfigApp" update-strategy="reload" >
<cm:default-properties>
<cm:property name="title" value="Default Title"/>
</cm:default-properties>
</cm:property-placeholder>

<bean id="myApp" init-method="refresh">
<property name="title" value="$\{title\}"></property>
</bean>
</blueprint>

上面xml请删除title附近的反斜杠。这个仅仅是了避免当wiki macro解析错误的影响。

部署配置文件

在我们已经成功地使用Config Admin服务后,进入产品环境唯一的事情就是部署bundle和一个默认配置。这个可以通过使用一个Karaf的feature文件来完成。我们根据需要的bunldes定义一个feature,和简单添加一个configfile元素。这个使得Karaf部署指定文件到karaf安装的etc目录下。如果文件已经存在,它不会被覆盖。

<feature name="tutorial-configadmin" version="${pom.version}">
<bundle>mvn:net.lr.tutorial.configadmin/configapp/${pom.version}</bundle>
<bundle>mvn:net.lr.tutorial.configadmin/configapp-blueprint/${pom.version}</bundle>
<configfile finalname="/etc/ConfigApp.cfg">mvn:net.lr.tutorial.configadmin/configadmin-features/${pom.version}/cfg</configfile>
</feature>

最后一个问题是怎么部署配置到maven使得configfile能够发现它。这个有点类似feature和build-helper-maven-plugin关系,详情请看pom文件怎么使用它。

总结和展望未来

在这个教程中,我们已经学习了Config Admin服务是怎么工作的以及如何使用OSGi和blueprint。我们也明白了如何编译及如何把文档和我们的工程部署在一起。

然而这里还是有一些非常有用的小细节没有涉及到。第一个细节是configfile不总是和config admin服务一致。实事上Karaf没有使用config admin服务去部署文件。我们所看到的是,已经存在的config元素不仅写配置到config admin服务中,而且持久化了它。幸运的是我的同事Jean Baptiste已经在研究这方面相关的,请访问Here

另外一个细节是对于企业环境,第一,需要定制化的config admin服务。例如需要在整网集中的地方设置配置和友好的UI界面。第二,是你不仅仅想要部署默认配置,而是部署对于系统管理确实需要的配置。所以针对安装的bunldes和feature和必要配置的修订,我认为你应该定一个部署计划。如果这个被正确的完成。将有利于部署和配置修订的检查,同时也有利于在某些配置错误的情况下去回滚修订。我希望我们可以在下一个Talend ESB EE发行版本提供一些相关功能。

参考文献

Using the Configuration Admin Service


myqrcode

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/z475382220/article/details/78852132

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法