osgi + felix example3编写与使用服务的改进

Posted 叶长风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了osgi + felix example3编写与使用服务的改进相关的知识,希望对你有一定的参考价值。

osgi + felix example3编写与使用服务的改进


上一篇博文中我们提及了如何对一个服务进行注册,但在example2和example2b中都没有对这个服务进行相应的使用,在本文中将对这个服务进行使用相应的使用,在felix的官网中,对该服务的使用方法是对目前已经注册的bundle进行扫描,然后使用服务,但是个人觉得Activator这种启动bundle最好只有一个,并且本文搭建了一个完整的环境,部署多个Activator bundle也不现实,因此本文采用了其他方法。


思路

在本文中,考虑的实现是在Bundle中再实现一次DictionaryService接口,然后在Activator中的start方法中进行这个服务的注册,并在随后的程序中进行相应的服务使用,不在对其他bundle进行扫描获取服务。


程序

之前的DictionaryService不再展示出来,在改动后的程序为:


package cn.com.example4;

import cn.com.example2.DictionaryService;
import org.osgi.framework.*;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;

/**
 * Created by Administrator on 2016/6/19.
 */
public class Activator implements BundleActivator, ServiceListener {

    //Bundle's context
    private BundleContext m_context = null;
    //The service reference being used.
    private ServiceReference m_ref = null;
    //The service object being used.
    private DictionaryService m_dictionary = null;

    public void start(BundleContext context) throws Exception {
        m_context = context;
        Hashtable<String, String> props = new Hashtable<String, String>();
        props.put("Language", "French");
        context.registerService(DictionaryService.class.getName(), new DictionaryImpl(), props);
        synchronized (this) {
            m_context.addServiceListener(this,  "(&(objectClass=" + DictionaryService.class.getName() + ")" +
                    "(Language=*))");
            //Query for any service references matching any language.
            ServiceReference[] refs = m_context.getServiceReferences(DictionaryService.class.getName(), "(Language=*)");
            //If we found any dictionary services, then just get
            //a reference to the first one so we can use it.
            if (refs != null) {
                m_ref = refs[0];
                m_dictionary = (DictionaryService)m_context.getService(m_ref);
            }
        }
        try {
            System.out.println("Enter a blank line to exit.");
            String word = "";
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            //Loop endlessly
            while (true) {
                //Ask the user to enter a word
                System.out.print("Enter word:");
                word = in.readLine();
                //If the user entered a blank line,then
                //exit the loop.
                if (word.length() == 0) {
                    break;
                } else if (m_dictionary == null) {
                    System.out.println("No dictionary available");
                } else if (m_dictionary.checkWord(word)) {
                    System.out.println("Correct.");
                } else {
                    System.out.println("Incorrect.");
                }
            }
        } catch (Exception e) {

        }
    }

    public void stop(BundleContext context) throws Exception {

    }

    public void serviceChanged(ServiceEvent event) {
        String[] objectClass = (String[]) event.getServiceReference().getProperty("objectClass");
        // If a dictionary service was registered, see if we
        // need one. If so, get a reference to it.
        if (event.getType() == ServiceEvent.REGISTERED)
        {
            if (m_ref == null)
            {
                // Get a reference to the service object.
                m_ref = event.getServiceReference();
                m_dictionary = (DictionaryService) m_context.getService(m_ref);
            }
        }
        // If a dictionary service was unregistered, see if it
        // was the one we were using. If so, unget the service
        // and try to query to get another one.
        else if (event.getType() == ServiceEvent.UNREGISTERING) {
            if (event.getServiceReference() == m_ref) {
                // Unget service object and null references.
                m_context.ungetService(m_ref);
                m_ref = null;
                m_dictionary = null;

                // Query to see if we can get another service.
                ServiceReference[] refs = null;
                try {
                    refs = m_context.getServiceReferences(
                            DictionaryService.class.getName(), "(Language=*)");
                } catch (InvalidSyntaxException ex) {
                    // This will never happen.
                }
                if (refs != null) {
                    // Get a reference to the first service object.
                    m_ref = refs[0];
                    m_dictionary = (DictionaryService) m_context.getService(m_ref);
                }
            }
        }
    }

    private static class DictionaryImpl implements DictionaryService {

        String[] m_dictionary = {
                "bienvenue", "au", "tutoriel", "osgi"
        };

        public boolean checkWord(String word) {
            word = word.toLowerCase();
            for (int i = 0;i < m_dictionary.length; i++) {
                if (m_dictionary[i].equals(word)) {
                    return true;
                }
            }
            return false;
        }
    }
}

在这个程序中,

context.registerService(DictionaryService.class.getName(), new DictionaryImpl(), props);

这段代码进行我们服务的注册,在以下一段代码中,我们进行了获取服务:

ServiceReference[] refs = m_context.getServiceReferences(DictionaryService.class.getName(), "(Language=*)");
m_dictionary = (DictionaryService)m_context.getService(m_ref);

如此,我们就可以使用相关的服务了。


程序运行

在程序启动之前,首先需要pom.xml中felix插件的Bundle-Activator的启动类,改为当前类后可以正常启动,现在运行程序观察结果:
这里写图片描述
可以观察到服务正常启动,输入osgi,显示结果为:
这里写图片描述
可以得到响应,说明服务正常提供,注册服务与使用服务均成功。


总结

  • 在以上服务进行相应的注册并使用,使用osgi传统的注册式服务是比较简单与方便的,但个人认为在Bundle中还是不要使用这种方式不断的注册服务和使用服务,这里的接口实现类最好还是不要放在Bundle内部,单独抽出来。

  • 在下节的编写中,将不再讲解felix官网的这些简单示例,将开始blueprint的讲解,同时这些服务的使用将会使用blueprint来管理,不再使用osgi的注册式服务与声明式服务。

  • 在后续的博文中,将开始osgi中一些深入的概念以及一些中间件的使用。

以上是关于osgi + felix example3编写与使用服务的改进的主要内容,如果未能解决你的问题,请参考以下文章

osgi + felix example1编写

osgi + felix example2编写

OSGI中blueprint简介

OSGI 与 Apache Felix

Felix/OSGi:如何使用不是 OSGi 服务的 SCR 组件?

如何使用felix实现osgi