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

GlassFish OSGi-JavaEE (二):深度剖析 WAB 規範與 Web 容器實現

     編輯:Java 相關知識

OSGi Web 應用規範核心:WAB (Web Application Bundle)

WAB 是 OSGi 企業級規範(Chapter 128)定義的 Web 部署單元,本質是 Bundle + WAR 混合體:

  • 擁有標準 OSGi 元數據(Bundle-SymbolicName, Import-Package 等)
  • 包含 Web 資源(WEB-INF/classes, WEB-INF/lib/*.jar, web.xml, 靜態資源)
  • 清單必須聲明 Web-ContextPath(如 /myapp)

WAB 結構示例

myapp.wab
├── META-INF/
│   └── MANIFEST.MF          # 關鍵 OSGi + Web 元數據
├── WEB-INF/
│   ├── classes/             # Servlet、Controller、Service
│   ├── lib/                 # 內部依賴 JAR
│   └── web.xml              # 可選,Servlet 3.0+ 可無
└── index.html, css/, js/    # 靜態資源

MANIFEST.MF 關鍵屬性

Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.example.myapp
Bundle-Version: 1.0.0
Web-ContextPath: /myapp
Import-Package: javax.servlet,javax.servlet.http,org.osgi.framework
Bundle-ClassPath: WEB-INF/classes,WEB-INF/lib/lib1.jar,WEB-INF/lib/lib2.jar
Export-Package: com.example.api;version="1.0"
  • Bundle-ClassPath 順序決定類加載優先級:WEB-INF/classes > WEB-INF/lib/*.jar,模仿 WAR 行為
  • 缺少 Web-ContextPath 視為普通 Bundle,不部署為 Web 應用

WAB 生命週期:四大擴展狀態

標準 Bundle 狀態: INSTALLED -> RESOLVED -> STARTING -> ACTIVE -> STOPPING -> UNINSTALLED
                    |
                    +-- WAB 專有狀態(由 Web Extender 管理):
                        DEPLOYING -> DEPLOYED -> UNDEPLOYING -> UNDEPLOYED
  • DEPLOYING:Web Extender 開始部署 Web 資源到 Web 運行時(Tomcat Catalina)
  • DEPLOYED:Web 應用已就緒,可服務請求(Bundle 處於 ACTIVE 或 STARTING)
  • UNDEPLOYING/UNDEPLOYED:停止/協載 Bundle 時同步卸載 Web 資源

OSGi Web 容器三大組件

構建 WAB:Maven + maven-bundle-plugin

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.3.4</version>
    <extensions>true</extensions>
    <configuration>
        <supportedProjectTypes>
            <supportedProjectType>war</supportedProjectType>
            <supportedProjectType>bundle</supportedProjectType>
        </supportedProjectTypes>
        <instructions>
            <_include>-osgi.properties</_include>
            <Export-Package>!*</Export-Package> <!-- 默認不導出,按需配置 -->
        </instructions>
    </configuration>
</plugin>

-osgi.properties 示例:

Web-ContextPath: /wabsample
Import-Package: javax.servlet;version="[3.0,4)",*
Bundle-SymbolicName: ${project.groupId}.${project.artifactId}

動態模塊化 Web 應用實戰

架構:Core (API) + Web Frontend (WAB) + Modules (Bundle)

  • Core:定義 Module 介面,導出 API 包
  • Web Frontend:JSF 2 + CDI,ServiceListener 監聽模塊註冊/註銷,動態更新頁面
  • Module 1/2:實現 Module 介面,BundleActivator 啟動時註冊服務

關鍵代碼:Web Frontend 動態發現模塊

@Named @ApplicationScoped
public class ApplicationBean {
    @Inject BundleContext bc;
    @Inject ModuleListener listener; // 實現 ServiceListener
    private List<Module> modules = new ArrayList<>();

    @Inject
    public void init(ServiceTracker tracker) {
        bc.addServiceListener(listener);
        loadExisting(tracker);
    }

    public void afterAddModule(Module m) { modules.add(m); }
    public void beforeRemoveModule(Module m) { modules.remove(m); }
    public List<Module> getModules() { return modules; }
}

GlassFish 部署三種方式

  1. asadmin deploy --type=osgi xxx.war(必須指定 --type=osgi)
  2. 自動部署:放入 domains/domain1/autodeploy/bundles/(推薦,支援依賴排序)
  3. asadmin osgi install/start/stop/uninstall(直接操作 OSGi 運行時)

GlassFish 內部部署流程深度剖析

階段 1:部署到 OSGi 運行時

asadmin deploy
    -> ApplicationLifecycle (核心入口)
        -> OSGiArchiveHandler (識別 --type=osgi)
        -> SnifferManager -> OSGiSniffer -> 返回容器類型 "osgi"
        -> ContainerRegistry -> OSGiContainer (HK2 Service)
            -> OSGiDeployer.install(bundle) -> Bundle.INSTALLED
            -> OSGiDeployer.start(bundle) -> Bundle.ACTIVE/STARTING

階段 2:部署到 Web 運行時(異步,由 Extender 觸發)

OSGiJavaEEActivator.start()
    -> ExtenderManager 啟動
        -> 註冊 JavaEEExtender
            -> BundleTracker 監聽 ACTIVE/STARTING Bundle
                -> HybridBundleTrackerCustomizer.addingBundle()
                    -> 線程池提交 OSGiContainer.deploy(bundle)
                        -> 遍歷 OSGiDeployer,OSGiWebDeployer.handles() 匹配 WAB
                        -> OSGiWebDeployer.deploy()
                            -> OSGiWebDeploymentRequest.execute()
                                -> preDeploy: ContextPathCollisionDetector 檢查衝突
                                -> prepare: 創建 WABClassLoader (繼承 WebappClassLoader)
                                -> deploy: 委托 ApplicationLifecycle 像部署 WAR 一樣展開
                                -> postDeploy: 註冊 ServletContext 為 OSGi 服務

關鍵類:WABClassLoader

public class WABClassLoader extends WebappClassLoader {
    // 核心:正確加載 WEB-INF/classes、WEB-INF/lib/*.jar、Bundle 導入包
    // 繼承 GlassFish Web 容器類加載器,支援 JSP 編譯、標籤庫等標準 Web 功能
}

思考與未來

  • Maven Archetype 自動化:正在開發 WAB 專用原型,一鍵生成標準結構
  • CDI BeanManager 跨 Bundle 共享:模塊 Bundle 中的 CDI Bean 目前無法被 Web WAB 發現,需 JSF/CDI 專家組協作解決
  • 遷移到標準化:OSGi R7+ 推動 Web Bundle 標準化,GlassFish 將持續跟進

WAB 實現了「不停機熱部署 Web 模塊」的工程級方案:核心業務穩定,邊緣功能動態插拔,適合金融、電信等高可用場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
組件職責GlassFish 實現
Web Extender監聽 Bundle 生命週期,驗證 WAB,部署/卸載 Web 應用org.glassfish.web.osgi.WebExtender
Web RuntimeServlet 容器,實際處理 HTTP 請求Tomcat Catalina (內嵌)
Web URL Handler處理 webbundle: 協議,支援 WAR 直接部署轉換為 WABorg.glassfish.web.osgi.WebUrlHandler