问题描述
项目描述:
我有一个简单的 Osgi 演示项目。域是一个具有多种传感器类型的气象站。每个传感器将其数据发送到气象站。通过 API,数据通过绘图在网站上公开和可视化。
目标:
例如:我目前有三种不同的传感器类型。一种用于测量风速、温度和湿度。 气象站应该有多个风传感器实例 (Cardinality.MULTIPLE)。
现状:
目前我正在通过创建一个 WindSpeedSensor 和一个 WindSpeedAdvancedSensor 服务来解决这个问题。我已经为 Apache Karaf 实现了一个自定义命令,我可以在其中向我的服务发送特定的配置命令。因此,传感器可以配置为在特定范围内生成测量值。
期望条件:
最佳解决方案是通过 Karaf 命令行启动额外的 WindSpeedSensor 实例。不应该需要人工WindSpeedSensors来实现WeatherStation类的多种服务的目标。
问题:
我怎样才能做到这一点?我是 Osgi 和声明式服务的新手,我很好奇 Osgi 的专家如何解决这个问题。提前感谢您抽出宝贵时间和反馈。
解决方法
您可以使用 Factory Configurations(参见 https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-deployment)。对于出厂 pid 下的每个配置,DS 都会创建一个组件配置。这允许根据配置管理中的工厂配置多次创建一个组件。
,我只将 OSGi 与 Karaf 一起使用,因此对于其他环境可能会有所不同。
如果您需要为每个配置文件提供 OSGi 服务,您可以使用声明性服务注释来设置此类服务,例如像这样。
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.metatype.annotations.Designate;
import com.example.service.config.ExampleServiceConfig;
@Component(
immediate = true,service = ExampleService.class,configurationPolicy = ConfigurationPolicy.REQUIRE,configurationPid = "com.example.service.ExampleService"
)
@Designate(ocd = ExampleServiceConfig.class,factory = true)
public class ExampleService {
@Activate
public void onServiceActivate(BundleContext context,ExampleServiceConfig config){
System.out.println(config.hello_message());
}
}
然后为服务定义类型安全的配置,例如:
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@ObjectClassDefinition(name = "ExampleService Configuration")
public @interface ExampleServiceConfig {
String hello_message() default "hello world";
String osgi_jndi_service_name() default "unique.service.name";
}
由于单例配置使用文件名,例如 <configurationPid>.cfg
工厂配置使用格式 <configurationPid>-<InstanceName>.cfg
,因此要创建上面 ExampleService
的两个实例,您可以创建例如以下配置:
com.example.service.ExampleService-InstanceA.cfg
hello.message=Hello from Instance A
osgi.jdni.service.name=InstanceA
com.example.service.ExampleService-InstanceB.cfg
hello.message=Hello from Instance B
osgi.jdni.service.name=InstanceB
至少在 Karaf 中,这将创建两个 ExampleService 实例和两个具有某种唯一 guid(而不是实例名称)的配置。要引用特定的服务实例,您可以使用引用注释中的目标属性。
@Reference(
target = "(osgi.jdni.service.name=InstanceA)"
)
ExampleService exampleService;