1、需要引入
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi</artifactId>
<version>3.0.0</version>
</dependency>
2、创建一个工厂类实现接口ManagedServiceFactory
public class WserviceFactory implements ManagedServiceFactory {
private static final Logger log = LoggerFactory.getLogger(WserviceFactory.class);
private BundleContext context;
private APIServices apiServices;
private String[] interfaces;
public BundleContext getContext() {
return context;
}
public void setContext(BundleContext context) {
this.context = context;
}
/**
* 服务:key为appid
*/
private final Map<String, ServiceRegistration> existingServices = new HashMap<>();
/**
* pid与appid的映射关系
*/
private final Map<String, String> PidNameMap = new HashMap<>();
public WserviceFactory() {
Class<?>[] allinterfaces = WwService.class.getInterfaces();
List<String> ifacelist = new ArrayList<>();
for (Class<?> iface : allinterfaces) {
ifacelist.add(iface.getName());
}
interfaces = (String[]) ifacelist.toArray(new String[ifacelist.size()]);
}
@Override
public String getName() {
return "JMust_Service";
}
@Override
public void updated(String pid, Dictionary dctnr) throws ConfigurationException {
log.info("JMust_Service update: pid=" + pid);
if (dctnr == null) {
log.warn("文件:" + pid + "为空,无法创建服务");
return;
}
String WwServiceName;
String WwSecret = null;
String WwAppID = dctnr.get("AppID").toString();
// 服务名不能空
if (WwAppID == null) {
log.warn(pid + "文件中AppID参数没有配置或者为空,无法创建服务!");
return;
} else {
WwSecret = dctnr.get("Secret").toString();
if (WxAppID.trim().isEmpty()) {
log.warn(pid + "文件中AppID参数没有配置或者为空,无法创建服务!");
return;
}
// 服务名不能重复
if (existingServices.containsKey(WwAppID)) {
if (WwAppID.equals(PidNameMap.get(pid))) {
// 同一配置文件修改的情况
log.info("更新已有的服务实例\"" + WwAppID + "\"");
ServiceRegistration ppcService;
ppcService = existingServices.get(WwAppID);
if (ppcService != null) {
log.info("Unregister WwService Instance:" + WwAppID);
ppcService.unregister();
} else {
log.warn("No WwService Instance:" + WwAppID);
}
existingServices.remove(WwAppID);
} else {
// 不同配置文件的服务实例名冲突
log.error("服务实例名\"" + WwAppID + "\"和其他配置文件里的服务实例名冲突,保留原有服务实例。");
return;
}
}
// 先清除当前配置文件原来对应的服务资源
String LegacyServiceName = PidNameMap.get(pid);
if (LegacyServiceName != null) {
ServiceRegistration ppcService = existingServices.get(LegacyServiceName);
if (ppcService != null) {
ppcService.unregister();
}
existingServices.remove(LegacyServiceName);
PidNameMap.remove(pid);
}
}
// 设置服务相关属性
ServiceRegistration ppcService;
Dictionary props = new Hashtable();
props.put("instance", WxAppID);
// 设置WwService相关属性
WxService instance = new WxService(WwAppID, WwSecret);
instance.setApiServices(apiServices);
if (instance == null) {
log.error("[" + pid + "]配置参数格式有误!创建WwService失败!");
return;
}
ppcService = context.registerService(interfaces, instance, props);
existingServices.put(WwAppID, ppcService);
PidNameMap.put(pid, WwAppID);
}
@Override
public void deleted(String pid) {
ServiceRegistration ppcService;
String ServiceName = PidNameMap.get(pid);
if (ServiceName != null) {
ppcService = existingServices.get(ServiceName);
if (ppcService != null) {
ppcService.unregister();
}
existingServices.remove(ServiceName);
PidNameMap.remove(pid);
}
}
public boolean isExistAppId(String appId) {
if (existingServices.containsKey(appId)) {
return true;
}
return false;
}
public void setApiServices(APIServices apiServices) {
this.apiServices = apiServices;
for (String key : existingServices.keySet()) {
WwService service = (WwService) context.getService(existingServices.get(key).getReference());
if (service != null) {
service.setApiServices(this.apiServices);
}
}
}
}
3、将相关属性初始化到需要用到的地方
public class WwService implements IWwService {
private String AppID;
private String Secret;
private APIServices apiServices;
public WxService(String appid, String secret) {
this.AppID = appid;
this.Secret = secret;
}
public void setApiServices(APIServices apiServices) {
this.apiServices = apiServices;
}
public APIServices getApiServices() {
return apiServices;
}
}
4、假如说,我们需要初始化的时候创建很多的服务,那么我们可以通过将所有的服务接口注入到一个接口服务类,看blueprint的配置,如:
<reference id="aService" interface="com.jmust.test.iface.IAAPI"
availability="optional" />
<reference id="bService" interface="com.jmust.test.iface.IBAPI"
availability="optional" />
<reference id="cService" interface="com.jmust.test.iface.ICAPI"
availability="optional" />
<reference id="dService" interface="com.jmust.test.iface.IDAPI"
availability="optional" />
<reference id="eService" interface="com.jmust.test.iface.IEAPI"
availability="optional" />
<reference id="fService" interface="com.jmust.test.iface.IFAPI"
availability="optional" />
<reference id="gService" interface="com.jmust.test.iface.IGAPI"
availability="optional" />
<reference id="hService" interface="com.jmust.test.iface.IHAPI"
availability="optional" />
<reference id="iService" interface="com.jmust.test.iface.IIAPI"
availability="optional" />
<reference id="jService"
interface="com.jmust.test.iface.IJAPI"
availability="optional" />
<reference id="kService" interface="com.jmust.test.iface.IKAPI"
availability="optional" />
<bean id="APIServicesBean" class="com.jmust.test.pwservice.Factory.APIServices">
<property name="aService" ref="aService" />
<property name="bService" ref="bService" />
<property name="cService" ref="cService" />
<property name="dService" ref="dService" />
<property name="eService" ref="eService" />
<property name="fService" ref="fService" />
<property name="gService" ref="gService" />
<property name="hService" ref="hService" />
<property name="iService" ref="iService" />
<property name="jService" ref="jService" />
<property name="kService" ref="kService" />
</bean>
5、将上面这些接口通过一个服务发布出去,这样子就相当于一次性发布了所有需要不发布的服务了
<!--服务配置后自动发布 -->
<bean id="WServiceFactory" class="com.jmust.test.pwservice.Factory.WserviceFactory">
<property name="context" ref="blueprintBundleContext" />
<property name="apiServices" ref="APIServicesBean" />
</bean>
<service id="WServiceFactoryService" ref="WServiceFactory"
interface="org.osgi.service.cm.ManagedServiceFactory">
<service-properties>
<entry key="service.pid" value="JMust_Service" />
</service-properties>
</service>
6、到此,将服务发布出去后,每当我们增加一个新的cfg文件,就会创建一份新的服务,从而达到了横向扩展了。
创建一个JMust_Service_0001.cfg文件,里面的内容是:
AppID=123456789
Secret=abcdefg
保存后,把他扔到servicemix的etc里面既可马上创建对应于这个cfg中的APPID为123456789的服务了;
假如说,我再创建一封新的cfg文件,就上面的APPID不一样外,保存,发布到etc下面,那么也会出马上创建一份服务
7、服务创建好之后,我们就需要应用这些服务了,那么该怎么办呢?
创建个实现类:
blueprint中监听服务public class ServiceRegister{ private BundleContext bundleContext; private static final Logger LOG = LoggerFactory.getLogger(ServiceRegister.class); public static final ConcurrentHashMap<String, IWwService> serviceMap = new ConcurrentHashMap<>(); public synchronized void register(ServiceReference<IWwService> reference) throws Exception { String appId = (String) reference.getProperty("instance"); IWwService service = bundleContext.getService(reference); serviceMap.put(appId, service); LOG.info("服务注册...." + reference.getBundle().getSymbolicName() + " AppID = " + appId); } public synchronized void unRegister(ServiceReference<IWwService> reference) throws Exception { if (reference == null || reference.getProperty("instance") == null) { return; } String appId = (String) reference.getProperty("instance"); if (serviceMap.containsKey(appId)) { serviceMap.remove(appId); } LOG.info("服务卸载...." + reference.getBundle().getSymbolicName() + " AppID = " + appId); } public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } }
<!--获取服务列表-->
<bean id="serviceRegister" class="com.jmust.test.service.ServiceRegister">
<property name="bundleContext" ref="blueprintBundleContext" />
</bean>
<reference-list availability="optional" interface="com.jmust.dest.pwservice.Iface.IWwService">
<reference-listener ref="serviceRegister" bind-method="register" unbind-method="unRegister" />
</reference-list>