OSGi 提供動態模塊化能力,但 JSF 依賴 Servlet 容器與 JSP 編譯器 (Jasper),Equinox 中 org.eclipse.equinox.jsp.jasper 需修改源碼以支援 JSF 標籤庫解析,導致整合門檻較高。本文提供完整可落地步驟。
org.eclipse.equinox.jsp.jasper 源碼。f:/h: 標籤庫 (具體修改點視 Equinox 版本而定,核心為標籤庫 URI 識別與 TLD 載入邏輯)。Bundle-ClassPath: ., lib/jsf-api.jar, lib/jsf-impl.jar, lib/jstl.jar, lib/standard.jar
Export-Package: org.danlley.jsf.beans
Import-Package: javax.faces.*, javax.servlet.*, javax.servlet.jsp.*, org.apache.jasper.*
Require-Bundle: org.eclipse.equinox.jsp.jasper, org.apache.jasper
<%@ taglib uri="https://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="https://java.sun.com/jsf/html" prefix="h" %>
<%@ page contentType="text/html;charset=UTF-8" %>
<html><body>
<f:view>
<h:form>
<h:outputText style="color:red" value="#{user.errMsg}" />
<h3>JSF Samples</h3>
Nick Name: <h:inputText value="#{user.id}" /><p>
<h:commandButton value="Submit" action="#{user.verify}" />
</h:form>
</f:view>
</body></html>
<%@ taglib uri="https://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="https://java.sun.com/jsf/html" prefix="h" %>
<%@ page contentType="text/html;charset=UTF-8" %>
<html><body>
<f:view>
<h:outputText value="#{user.id}" /> Welcome!
<h3>JavaServer Faces!</h3>
</f:view>
</body></html>
package org.danlley.jsf.beans;
public class UserBean {
private String id, pwd, errMsg;
// Getter/Setter 省略
public String verify() {
if ("JsfUser".equals(id)) return "success";
setErrMsg("userID should be JsfUser");
return "failed";
}
}
<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failed</from-outcome>
<to-view-id>/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>
| 層面 | 傳統 Web 應用 | OSGi + JSF |
|---|---|---|
| 類加載 | 單一 ClassLoader | Bundle ClassLoader 隔離,需正確 Import/Export JSF API/Impl 包 |
| JSP 編譯 | 容器內建 Jasper | Equinox Jasper Bundle 需修改支援 JSF 標籤庫 URI |
| 生命週期 | ServletContextListener | BundleActivator start/stop 掛載 FacesServlet、載入 faces-config |
| 資源訪問 | ServletContext.getResource | BundleContext.getResource / ClassLoader.getResourceAsStream |
| 熱部署 | 整體重啟/熱替換受限 | Bundle 級動態安裝/更新/協載,JSF 狀態需妥善遷移 |
jsf-impl.jar,避免多版本類加載錯誤。javax.el.ExpressionFactory 綁定正確實現 (如 JBoss EL / GlassFish EL)。/images/*, /css/* 至 Bundle 內 WebContent 目錄。OSGi + JSF 整合雖涉及 Jasper 修改等深水區,但通過模塊化獲得的動態擴展、版本隔離、熱部署能力,對大型長期演進系統極具價值。掌握核心類加載與標籤庫解析機制,配合 Facelets 現代化 VDL,可構建健壯的模塊化企業級 Web 應用。