OSGI实战

插件工程(Bundle)

依赖

        <dependency>
            <groupId>org.eclipse.tycho</groupId>
            <artifactId>org.eclipse.osgi</artifactId>
            <version>3.11.0.v20160603-1336</version>
        </dependency>

IDEA中使用OSGI

安装OSGI插件,后根据一下链接操作https://blog.csdn.net/u010597819/article/details/105455269?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-5-105455269-blog-82585930.pc_relevant_aa2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-5-105455269-blog-82585930.pc_relevant_aa2&utm_relevant_index=8​​​​​​

编写代码

Bundle的启动类(implements BundleActivator)

package org.jsq;

import lombok.extern.slf4j.Slf4j;
import org.jsq.internal.PrintAdapter;
import org.jsq.internal.QueryAdapter;
import org.jsq.service.Adapter;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

import java.util.*;

@Slf4j
public class FirstBundleActivator implements BundleActivator {
    private static final String CMD_NAME = "cmdname";


    private List<ServiceRegistration<Adapter>> registrations = new ArrayList<>();

    @Override
    public void start(BundleContext context) throws Exception {
        log.info("start to FirstBundleActivator");
        registrations.add(context.registerService(Adapter.class, new PrintAdapter(), buildMetadata("print")));
        log.info("register service of print");
        registrations.add(context.registerService(Adapter.class, new QueryAdapter(), buildMetadata("query")));
        log.info("register service of query");
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        log.info("stop to FirstBundleActivator");
        registrations.forEach(ServiceRegistration::unregister);
    }

    private Dictionary<String,String> buildMetadata(String value) {
        return (Dictionary<String, String>) new Properties().setProperty(CMD_NAME, value);
    }
}

Adapter接口(Bundle中相同位置也需要一份,且Bundle中需要导入)

package org.jsq.service;

import java.util.Map;

public interface Adapter {
    Map<String, Object> run(Map<String, Object> data);

}

接口的各实现类

package org.jsq.internal;

import org.jsq.service.Adapter;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@Slf4j
public class PrintAdapter implements Adapter {
    @Override
    public Map<String, Object> run(Map<String, Object> data) {
        log.info("start to print");
        return ImmutableMap.of("result", "ok");
    }
}
package org.jsq.internal;

import org.jsq.service.Adapter;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
@Slf4j
public class QueryAdapter implements Adapter {
    @Override
    public Map<String, Object> run(Map<String, Object> data) {
        log.info("start to query");
        return ImmutableMap.of("result", "ok");
    }
}

compile后build module,生成MANIFEST.MF

里面内容

Manifest-Version: 1.0
Bnd-LastModified: 1657447896210
Bundle-Activator: org.jsq.FirstBundleActivator
Bundle-ManifestVersion: 2
Bundle-Name: org.jsq
Bundle-SymbolicName: org.jsq
Bundle-Version: 1.0.0
Created-By: 1.8.0_161 (Oracle Corporation)
Export-Package: org.jsq;uses:="org.osgi.framework";version="1.0.0",org
 .jsq.service;version="1.0.0"
Import-Package: com.google.common.collect,org.jsq.service,org.osgi.fra
 mework,org.slf4j
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Tool: Bnd-5.1.2.202007211702

其中org.jsq.service是外部调用工程Adapter接口的存放位置,Import-Package是需要外面导入Bundle中是用的类(Bundle中由pom.xml引入),Export-Package是bundle中导出的内容,Bundle-Activator: org.jsq.FirstBundleActivator是启动类

代用Bundle工程

依赖

        <dependency>
            <groupId>org.eclipse.tycho</groupId>
            <artifactId>org.eclipse.osgi</artifactId>
            <version>3.11.0.v20160603-1336</version>
        </dependency>

RESTful接口触发加载或刷新bundle.jar

    @PostMapping("/execute")
    public ResponseEntity<Map<String, Object>> execBundle(@RequestBody Map<String, Object> body) {
        try {
            log.info("body is {}",body);
            BundleService instance = BundleService.getInstance();
            Adapter adapter = instance.getAdapter((String) body.getOrDefault("cmdname", "print"));
            if (null != adapter) {
                Map<String, Object> result =  adapter.run(body);
                return ResponseEntity.ok(ImmutableMap.of("code", 0, "message", "success", "result", result));
            }
        } catch (RuntimeException e) {
            log.error("start bundle error", e);
        }
        return ResponseEntity.ok(ImmutableMap.of("code", 1, "message", "failure"));
    }

创建和启动osgi框架

public void startFramework() {
        try {
            log.info("start framework");
            for (FrameworkFactory frameworkFactory : ServiceLoader.load(FrameworkFactory.class)) {
                Map<String, String> config = new HashMap<>(2);
                String importPackage = loadImportPackage(JAR_PATH);
                config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, importPackage);
                config.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
                log.info("config of framework is {}", config);
                framework = frameworkFactory.newFramework(config);
                framework.init();
                framework.start();
            }
        } catch (IOException | BundleException e) {
            log.error("Failed to start bundle", e);
            throw new RuntimeException("Failed to start bundle", e);
        }
    }

加载或刷新Bundle.jar

private void refreshToLatestBundle(BundleVersionManager latestBundle) {
        Optional<URI> bundleURI = latestBundle.getBundleURI();
        if (bundleURI.isPresent()) {
            Bundle bundle = framework.getBundleContext().getBundle(bundleURI.get().toString());
            log.info("bundle is {}", bundle);
            if (null != bundle) {
                if (bundle.getVersion() == null || latestBundle.getBundleVersion() == null) {
                    return;
                }
                log.info("start to refresh bundle");
                stopAndUninstallBundle(bundle);
            }
            installBundle(bundleURI);
        }
    }

    private void installBundle(Optional<URI> bundleURI) {
        try {
            log.info("url of bundle is {}", bundleURI.get());
            Bundle newBundle = framework.getBundleContext().installBundle(bundleURI.get().toString());
            newBundle.start();
            log.info("id is {},name is {}, version is {}, in {}, when {} ", newBundle.getBundleId(), newBundle.getSymbolicName(),
                    newBundle.getVersion(), newBundle.getLocation(), newBundle.getLastModified());
        } catch (BundleException e) {
            log.error("Failed to install Bundle", e);
        }
    }

    private void stopAndUninstallBundle(Bundle bundle) {
        try {
            bundle.stop();
            bundle.uninstall();
        } catch (BundleException e) {
            log.error("Failed to stop and uninstall bundle", e);
        }
    }

获得bundle中具体的Adapter类

public Adapter getAdapter(String name) {
        try {
            log.info("start to get Adapter");
            for (Bundle bundle : framework.getBundleContext().getBundles()) {
                log.info("id is {},name is {}, version is {}, in {}, when {} ", bundle.getBundleId(), bundle.getSymbolicName(), bundle.getVersion(), bundle.getLocation(), bundle.getLastModified());
                if (bundle.getLocation().contains(JAR_PATH)) {
                    ServiceReference<?>[] serviceReferences = bundle.getBundleContext().getServiceReferences(Adapter.class.getName(), null);
                    log.info("serviceReferences is {}", serviceReferences);
                    if (null != serviceReferences && serviceReferences.length > 0) {
                        Adapter service = (Adapter) framework.getBundleContext().getService(serviceReferences[0]);
                        log.info("name of Adapter is {}",service.getClass().getName());
                        return service;
                    }
                }
            }
            throw new BundleException("no Adapter");
        } catch (InvalidSyntaxException | BundleException e) {
            log.error("Failed to getAdapter", e);
        }
        return null;
    }

完整代码

https://gitee.com/jiang-shiqing-is-me/working-learn/tree/master/Java%E5%BC%80%E5%8F%91%E5%B8%B8%E7%94%A8%E5%8A%9F%E8%83%BD/osgi

参考

https://www.jianshu.com/p/1751046d1491

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值