首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2EE

打造 Hello World OSGi Web 應用:程式化與聲明式 HTTP 服務註冊雙範式

     編輯:J2EE

「Hello OSGi」系列第三篇,手把手構建包含靜態 HTML 與 Servlet 的 OSGi Web Bundle,對比程式化註冊(Java 代碼調用 HttpService API)與聲明式註冊(plugin.xml 擴展點)兩種風格,幫助開發者根據專案需求選擇最適合的方式。

共同基礎:Bundle 結構與靜態資源

  • Bundle SymbolicName:com.javaworld.sample.osgi.web.programmatic / ...declarative
  • 靜態資源:helloworld.html(輸出 "Hello From helloworld.html")
  • Servlet:HelloWorldServlet 繼承 HttpServlet,doGet() 輸出 "Hello from HelloWorldServlet"

方式一:程式化註冊 —— 完全掌控,適合動態邏輯

1. MANIFEST.MF 匯入必要包

Import-Package: javax.servlet;version="2.4.0",
 javax.servlet.http;version="2.4.0",
 org.osgi.framework;version="1.3.0",
 org.osgi.service.http;version="1.2.0",
 org.osgi.util.tracker;version="1.3.2"

2. Activator 啟動時透過 ServiceTracker 追蹤 HttpService

public class Activator implements BundleActivator {
    ServiceTracker httpServiceTracker;
    public void start(BundleContext context) {
        httpServiceTracker = new HttpServiceTracker(context);
        httpServiceTracker.open();
    }
    public void stop(BundleContext context) {
        httpServiceTracker.close();
    }
}

3. HttpServiceTracker 實作註冊/註銷邏輯

public class HttpServiceTracker extends ServiceTracker {
    public HttpServiceTracker(BundleContext context) {
        super(context, HttpService.class.getName(), null);
    }
    public Object addingService(ServiceReference ref) {
        HttpService httpService = (HttpService) context.getService(ref);
        try {
            // 靜態資源映射:URL → Bundle 內路徑
            httpService.registerResources("/helloworld.html", "/helloworld.html", null);
            // Servlet 映射:URL → Servlet 實例
            httpService.registerServlet("/helloworld", new HelloWorldServlet(), null, null);
        } catch (Exception e) { e.printStackTrace(); }
        return httpService;
    }
    public void removedService(ServiceReference ref, Object svc) {
        HttpService httpService = (HttpService) svc;
        httpService.unregister("/helloworld.html");
        httpService.unregister("/helloworld");
        super.removedService(ref, svc);
    }
}

關鍵點:

  • ServiceTracker 解決 HttpService 動態可用性:Bundle 啟動順序不固定,Tracker 確保服務就緒才註冊。
  • registerResources(alias, path, HttpContext) 將 Bundle 內資源掛載至 HTTP 命名空間。
  • registerServlet(alias, servlet, initParams, HttpContext) 掛載 Servlet,支援初始化參數。
  • 停用時必須 unregister,觸發 Servlet destroy() 生命週期。

驗證:https://localhost/helloworld.html、https://localhost/helloworld

方式二:聲明式註冊 —— 零代碼,適合靜態配置

1. MANIFEST.MF 要求

Import-Package: javax.servlet;version="2.4.0",
 javax.servlet.http;version="2.4.0"
Require-Bundle: org.eclipse.equinox.http.registry

依賴 Equinox 專屬 http.registry Bundle,犧牲可移植性換取零代碼。

2. plugin.xml 定義擴展點

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
  <extension point="org.eclipse.equinox.http.registry.servlets">
    <servlet alias="/decl/helloworld"
             class="com.javaworld.sample.osgi.web.webapp.HelloWorldServlet"/>
  </extension>
  <extension point="org.eclipse.equinox.http.registry.resources">
    <resource alias="/decl/helloworld.html" base-name="/helloworld.html"/>
  </extension>
</plugin>

框架啟動時自動讀取 plugin.xml,向 HttpService 註冊對應資源與 Servlet。修改 URL 僅需改 XML,無需重新編譯 Java 代碼。

驗證:https://localhost/decl/helloworld.html、https://localhost/decl/helloworld

兩種方式對比與選型建議

維度程式化註冊聲明式註冊
可移植性標準 OSGi API,跨運行時依賴 Equinox http.registry,鎖定平台
動態性運行時可根據條件決定註冊邏輯靜態 XML,部署後固定
維護性Java 代碼重構友好,IDE 支援完善XML 修改即時生效,適合運維調整
依賴管理需手動追蹤 HttpService(ServiceTracker)框架自動管理生命週期
適用場景需動態掛載、多租戶、條件註冊固定端點、標準 Web 模組、追求零樣板

下一步:走出 Eclipse,部署到生產環境

下一篇(系列最終篇)將詳細講解如何在命令列啟動 Equinox、安裝啟動 Bundle、嵌入 Jetty;以及如何打包 bridge.war 部署至 Tomcat,實現 OSGi 容器與傳統 Servlet 容器共生。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved