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 容器三大組件
| 組件 | 職責 | GlassFish 實現 |
| Web Extender | 監聽 Bundle 生命週期,驗證 WAB,部署/卸載 Web 應用 | org.glassfish.web.osgi.WebExtender |
| Web Runtime | Servlet 容器,實際處理 HTTP 請求 | Tomcat Catalina (內嵌) |
| Web URL Handler | 處理 webbundle: 協議,支援 WAR 直接部署轉換為 WAB | org.glassfish.web.osgi.WebUrlHandler |
構建 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 部署三種方式
asadmin deploy --type=osgi xxx.war(必須指定 --type=osgi)
- 自動部署:放入
domains/domain1/autodeploy/bundles/(推薦,支援依賴排序)
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 模塊」的工程級方案:核心業務穩定,邊緣功能動態插拔,適合金融、電信等高可用場景。
- 上一篇文章: Spring 事務管理五大配置方式全解析:從 XML 到全注解
- 下一篇文章: Spring PropertyPlaceholderConfigurer 讀取 properties 配置完全指南
Copyright ©
程式碼之家 All Rights Reserved