JavaServer Faces (JSF) 導航框架透過聲明式配置定義視圖(View)間的頁面流轉邏輯。配置集中於 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>
省略 from-outcome 即為預設案例,匹配所有未明確定義的 outcome:
<navigation-case>
<to-view-id>/pages/goodbye.jsp</to-view-id>
</navigation-case>
from-view-id 支援尾部星號通配,星號必須位於字串末尾:
<navigation-rule>
<from-view-id>/pages/*</from-view-id>
<navigation-case>
<from-outcome>menu</from-outcome>
<to-view-id>/menu/main.jsp</to-view-id>
</navigation-case>
</navigation-rule>
無效模式:/pages/*.jsp(星號非尾部)、/*/page(星號非尾部)
具體路徑優於通配符路徑:
<!-- 規則 1:通用規則 -->
<navigation-rule>
<from-view-id>/pages/*</from-view-id>
<navigation-case>
<from-outcome>info</from-outcome>
<to-view-id>/menu/generalHelp.html</to-view-id>
</navigation-case>
</navigation-rule>
<!-- 規則 2:具體規則(優先生效) -->
<navigation-rule>
<from-view-id>/pages/login.jsp</from-view-id>
<navigation-case>
<from-outcome>info</from-outcome>
<to-view-id>/menu/loginHelp.html</to-view-id>
</navigation-case>
</navigation-rule>
訪問 /pages/login.jsp 且 outcome 為 info 時,規則 2 生效,導向 /menu/loginHelp.html。
兩種等效寫法實現「任意頁面均可導向幫助頁」:
<!-- 寫法 1:通配符 -->
<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>
<!-- 寫法 2:省略 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>無任何效果,必須使用*或完全省略該元素。
相同 from-view-id + 相同 from-outcome 指向不同目標時,配置檔中後定義者勝出。多檔案情況下,依 web.xml 中 CONFIG_FILES 列表順序,最後載入檔案的規則生效。
同一 from-view-id 可拆分為多個 navigation-rule 分散定義:
<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-rule>
<navigation-rule>
<from-view-id>/pages/inputname.jsp</from-view-id>
<navigation-case>
<from-outcome>sayGoodbye</from-outcome>
<to-view-id>/pages/goodbye.jsp</to-view-id>
</navigation-case>
</navigation-rule>
運行時效果等同於合併在單一規則中,便於團隊協作與模組化管理。
<h:commandButton id="submit" action="sayHello" value="Submit" />
<h:commandButton id="submit" action="#{GetNameBean.helloAction}" value="Submit" />
Managed Bean 方法簽名:public String helloAction() { return "sayHello"; }
<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-action>#{GetNameBean.helloAction}</from-action>
<from-outcome>sayHello</from-outcome>
<to-view-id>/pages/hello.jsp</to-view-id>
</navigation-case>
</navigation-rule>
當 sayHello 由 #{GetNameBean.helloAction} 產生時,第二個 case 生效(更精確匹配)。若由靜態 action="sayHello" 觸發,則第一個 case 生效。
頁面按鈕:<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-action>#{GetNameBean.helloAction}</from-action>
<from-outcome>sayHello</from-outcome>
<to-view-id>/b.jsp</to-view-id>
</navigation-case>
</navigation-rule>
結果:導向 /b.jsp。原因:第二個規則包含 from-action 精確匹配 Action 來源,優先級高於第一個僅匹配 outcome 的規則。
from-view-id,避免過度依賴通配符from-action 實現同一 Outcome 不同來源的差異化導航from-view-id 而非空元素