JSF 標籤與 JSTL (及其他自定義標籤) 大程度可混合使用。JSF <f:view> 定義組件樹根節點,內部可嵌套 JSTL 標籤;反之 JSTL 結構中亦可嵌套 JSF 組件。工具廠商態度:IBM 勸勉混合,Sun Creator 偏純 JSF,Oracle JDeveloper 允許混合但勸純 JSF。
當 JSF 標籤嵌套在非 JSF 自定義標籤內時,必須為 JSF 標籤指定
id屬性,以確保組件樹正確構建與狀態保存。
<f:verbatim> 包裝 XML/HTML 片段<%@ taglib uri="https://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="https://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="https://java.sun.com/jstl/core" prefix="c" %>
<f:view>
<h1><h:outputText value="Example of using JSF tags with other custom tags" /></h1>
<p><b><c:out value="Here's the value of your web.xml (don't do this at home):" /></b></p>
<blockquote>
<f:verbatim>
<c:import url="WEB-INF/web.xml" />
</f:verbatim>
</blockquote>
</f:view>
<c:import> 引入 XML 文件,輸出包含標記字符,必須包裹在 <f:verbatim> 中,否則 JSF 渲染器會嘗試解析導致異常或輸出錯亂。<f:verbatim> 是 UIOutput 組件,負責轉義輸出模板文本,確保 XML/HTML 片段在頁面原樣呈現。HtmlDataTable, HtmlPanelGrid 等) 內部的模板文本同樣需用 <f:verbatim> 包裹。<f:view>
<jsp:useBean class="org.jia.examples.TestForm" id="exampleBean" scope="session" />
<h1><h:outputText value="Example of using JSF and JSTL expression languages" /></h1>
<h:form>
<h:outputLabel for="inputInt">
<h:outputText value="How many times do you want to repeat the Oracle's prophecy?" />
</h:outputLabel>
<h:inputText id="inputInt" value="#{sessionScope.exampleBean.number}" />
<h:commandButton value="Go!" />
</h:form>
<p>
<c:if test="${sessionScope.exampleBean.number > 0}">
<c:forEach begin="0" end="${sessionScope.exampleBean.number - 1}" var="count">
Queen Tracey will achieve world domination.<br/>
</c:forEach>
</c:if>
</p>
</f:view>
| 層面 | JSF EL (#{...}) | JSTL EL (${...}) |
|---|---|---|
| 求值時機 | 延遲求值 (Deferred) - 生命週期各階段按需求值 | 即時求值 (Immediate) - 頁面編譯/渲染時求值 |
| 讀寫性 | 可讀可寫 (ValueExpression 支援 setValue) | 僅讀 (ValueExpression 僅 getValue) |
| 作用域引用 | #{sessionScope.bean.prop} | ${sessionScope.bean.prop} |
| 共享前提 | Backing Bean 需註冊為 Managed Bean 或 <jsp:useBean> 放入作用域 | 同樣從作用域 Map 獲取 |
示例中 <jsp:useBean> 將 TestForm 實例放入 Session (exampleBean),JSF <h:inputText> 雙向綁定 #{sessionScope.exampleBean.number},JSTL <c:if/forEach> 讀取同一屬性 ${sessionScope.exampleBean.number} 進行邏輯判斷與迭代,實現單一數據源、雙框架無縫協作。
c:*,運行期執行 ui:*/f:*/h:*),消除 JSP 混合模式的生命週期時序衝突,獲得更好模板復用與類型安全。<c:forEach> 中動態生成 JSF 組件: JSTL 執行於視圖構建期,JSF 組件樹構建於渲染期,易導致組件 ID 衝突、狀態丟失、AJAX 失效。改用 <ui:repeat> / <h:dataTable> 等 JSF 原生迭代組件。#{} 與 ${} 語義差異,但求值時機差異 (延遲/即時) 依然存在,需清晰理解。JSF + JSTL 混合是過渡期實用技術,核心在於 作用域共享 JavaBean + <f:verbatim> 包裝非組件文本 + 理解 EL 求值時機差異。新架構請拥抱 Facelets + 統一 EL + 純 JSF 組件樹,將邏輯下沉至 Backing Bean,視圖層純宣告式渲染。