JSF 導航規則定義於 faces-config.xml,支援模組化拆分。在 web.xml 中聲明多配置文件:
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml,/WEB-INF/faces-beans.xml</param-value>
</context-param>
載入順序決定規則優先級:後載入文件的同名規則覆蓋先載入者。
<navigation-rule>
<from-view-id>/pages/inputname.jsp</from-view-id>
<navigation-case>
<from-outcome>sayHello</from-outcome>
<to-view-id>/pages/greeting.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>sayGoodbye</from-outcome>
<to-view-id>/pages/goodbye.jsp</to-view-id>
</navigation-case>
</navigation-rule>
三要素:來源視圖、結果碼、目標視圖。
<navigation-case>
<from-outcome>sayHello</from-outcome>
<to-view-id>/pages/greeting.jsp</to-view-id>
</navigation-case>
<navigation-case>
<!-- 缺少 from-outcome,匹配所有非 sayHello 的結果 -->
<to-view-id>/pages/goodbye.jsp</to-view-id>
</navigation-case>
<navigation-rule> <from-view-id>/pages/*</from-view-id> <navigation-case> <from-outcome>menu</from-outcome> <to-view-id>/menu/main_main.jsp</to-view-id> </navigation-case> </navigation-rule>限制:
*必須位於字串末尾,/pages/*.jsp為非法模式。3. 全域結果碼(跨視圖跳轉)
<!-- 寫法一:顯式 * --> <navigation-rule> <from-view-id>*</from-view-id> <navigation-case> <from-outcome>globalHelp</from-outcome> <to-view-id>/help/index.html</to-view-id> </navigation-case> </navigation-rule> <!-- 寫法二:省略 from-view-id --> <navigation-rule> <navigation-case> <from-outcome>globalHelp</from-outcome> <to-view-id>/help/index.html</to-view-id> </navigation-case> </navigation-rule>陷阱:
<from-view-id></from-view-id>(空元素)不生效,等同於無規則。規則衝突解決機制
- 具體優先於通用:
/pages/login.jsp精確匹配優先於/pages/*模式匹配。- 後載入覆蓋先載入:多文件衝突時,
web.xml列表中靠後文件勝出。- 同文件最後定義勝出:同一
from-view-id+from-outcome重複,最後一條生效。規則拆分與重組
單一
navigation-rule可拆分為多個片段分散在文件各處甚至跨文件,運行時自動合併。建議:
faces-nav-admin.xml、faces-nav-user.xml)navigation-rule 內,利於維護<!-- 靜態結果碼 -->
<h:commandButton action="sayHello" value="Submit" />
<!-- 動態結果碼:調用 Bean 方法返回字串 -->
<h:commandButton action="#{GetNameBean.helloAction}" value="Submit" />
<navigation-rule>
<from-view-id>/pages/inputname.jsp</from-view-id>
<navigation-case>
<from-outcome>sayHello</from-outcome>
<to-view-id>/pages/anotherhello.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>sayHello</from-outcome>
<from-action>#{GetNameBean.helloAction}</from-action>
<to-view-id>/pages/hello.jsp</to-view-id>
</navigation-case>
</navigation-rule>
若 sayHello 由 GetNameBean.helloAction 產生,命中第二條;否則命中第一條。實現「同結果碼、不同業務來源、不同跳轉目標」的精準路由。
<h:commandButton action="#{GetNameBean.helloAction}" />
<navigation-rule>
<from-view-id>/pages/inputname.jsp</from-view-id>
<navigation-case>
<from-outcome>sayHello</from-outcome>
<to-view-id>/a.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/pages/*</from-view-id>
<navigation-case>
<from-outcome>#{GetNameBean.helloAction}</from-outcome>
<to-view-id>/b.jsp</to-view-id>
</navigation-case>
</navigation-rule>
答案:跳轉至 /b.jsp。原因:第二條規則的 from-outcome 為 EL 表達式 #{GetNameBean.helloAction},若 Bean 方法返回 "sayHello",則 from-outcome 匹配 "sayHello";同時 from-view-id 模式 /pages/* 匹配 /pages/inputname.jsp。雖然第一條規則精確匹配視圖,但第二條規則同時匹配 from-outcome(動態值)與 from-view-id(模式),且載入順序靠後(或同文件後定義),依「具體優先、後載入勝出」原則生效。
from-action 綁定 Bean 方法,避免魔術字串散落頁面from-view-id 寫法web.xml 載入順序:通用規則在前,業務覆蓋規則在後javax.faces.FACELETS_REFRESH_PERIOD 熱加載驗證規則即時生效