天天看點

利用OSGi DS實作可配置Web應用程式初探

現在來試試怎樣用DS實作動态配置一個Web應用程式界面裡菜單,使用的OSGi實作還是Equinox。Eclipse裡菜單項是通過實作actionSets、editorActions等等擴充點添加的,在OSGi裡沒有這些“擴充點”,沒關系,我們可以自己定義。

一、用一個Bundle定義Java接口檔案,和Eclipse擴充點的功能類似,這些接口可以作為服務的接入點。例子裡這個Bundle的ID是net.bjzhanghao.osgi.services,接口類是IMenuContributor,内容很簡單如下所示:

public interface IMenuContributor {

    public List<MenuItem> getItems();

}

上面用到的MenuItem是自己定義的一個簡單的資料結構,包含name和url兩個String類型的成員變量和相應的getter/setter方法,這裡就不展示了。

二、用0..n個Bundle實作上面定義的接口(暫時稱之為Contributor),并聲明為服務。例子裡有兩個這樣的Bundle,ID分别是net.bjzhanghao.osgi.menu.contributor和net.bjzhanghao.osgi.menu.contributor2,實作類都是MyMenuContributor,前者提供了Menu1..3,後者提供了Menu4..5;以下是服務的聲明,即項目裡OSGI-INF/component.xml檔案的内容:

<?xml version="1.0" encoding="UTF-8"?>

<component name="services">

    <implementation 

        class="net.bjzhanghao.osgi.menu.contributor.MyMenuContributor"/> 

    <service>

        <provide interface="net.bjzhanghao.osgi.services.IMenuContributor"/>

    </service>

</component>

MyMenuContributor實作IMenuContributor,你可以任意實作它,例子裡是讓它提供三個菜單項:

public class MyMenuContributor implements IMenuContributor {

    public List<MenuItem> getItems() {

        List<MenuItem> list = new ArrayList<MenuItem>();

        list.add(new MenuItem("Menu1", null));

        list.add(new MenuItem("Menu2", null));

        list.add(new MenuItem("Menu3", null));

        return list;

    }

三、現在SOA的一半工作也就是注冊服務的部分完成了,剩下要做的是另一半,消費這些服務。首先在web應用程式Bundle裡,建立一個Helper類收集這些服務,這個Helper類的功能相當于一個Registry。例子裡這個Bundle的ID是net.bjzhanghao.osgi.example,Helper類是MenuHelper;以下是對MenuHelper的配置,即項目裡OSGI-INF/component.xml檔案的内容,這樣OSGi在啟動Bundle時會把實作IMenuContributor的服務通過addMenuContributor方法注冊到MenuHelper裡,注意cardinality的值要為"0..n",policy的值要為"dynamic":

<component name="menuHelper">

    <implementation     

        class="net.bjzhanghao.osgi.example.MenuHelper"/>   

    <reference name="menuHelper"

        interface="net.bjzhanghao.osgi.services.IMenuContributor"

        cardinality="0..n"

        policy="dynamic"

        bind="addMenuContributor"

        unbind="removeMenuContributor"

    />

四、在JSP/Servlet裡,利用上面的Helper類構造界面(或業務邏輯)。因為我們定義的接口是關于菜單的,是以例子應用的菜單會根據Bundle配置(啟動/停止)變化。例子裡是在ExampleServlet裡實作的,代碼很簡單如下所示:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    resp.setContentType("text/html");

    resp.getWriter().write("Hello<br/>");

    resp.getWriter().write("<ul>");

    for (IMenuContributor menuContributor : MenuHelper.getInstance().getMenuContributors()) {

        for (MenuItem mItem : menuContributor.getItems()) {

            resp.getWriter().write("<li><a href=\"" + mItem.getUrl() + "\">" + mItem.getName() + "</a></li>");

        }

    resp.getWriter().write("</ul>");

五、執行方式:

1、在Eclipse裡導入代碼包裡所有項目,啟動上述所有項目及其依賴的項目(Add Required Bundles),見下圖:

2、在浏覽器裡輸入位址http://localhost/exampleServlet,應該可以看到五個菜單項,見下圖(這個簡單的例子裡沒有考慮順序問題,是以Menu4..5可能出現在前面,使用類似Eclipse裡為Menu預留位置的方式可以解決):

3、回到Eclipse,在Console裡輸入ss檢視目前的Bundle,應該可以看到類似下圖的内容:

4、在Console裡輸入stop 35(35是Contributor的Bundle序号),Console會提示“Calling removeMenuContributor”,然後到浏覽器裡重新整理頁面,應該看到菜單項隻剩下Menu4..5。

<a href="http://files.cnblogs.com/bjzhanghao/net.bjzhanghao.osgi.example2.zip">代碼下載下傳</a>

繼續閱讀