JSF - 页面导航
导航规则是 JSF 框架提供的规则,用于描述单击按钮或链接时要显示哪个视图。
导航规则可以在名为 faces-config.xml 的 JSF 配置文件中定义。它们可以在托管 bean 中定义。
导航规则可以包含显示结果视图所基于的条件。JSF 2.0 也提供了隐式导航,无需定义导航规则。
隐式导航
JSF 2.0 提供了名为隐式导航的自动视图页面解析器机制。在这种情况下,您只需将视图名称放在操作属性中,JSF 就会在部署的应用程序中自动搜索正确的 视图 页面。
JSF 页面中的自动导航
在任何 JSF UI 组件的操作属性中设置视图名称。
<h:form> <h3>Using JSF outcome</h3> <h:commandButton action = "page2" value = "Page2" /> </h:form>
此处,当单击 Page2 按钮时,JSF 将解析视图名称 page2 作为 page2.xhtml 扩展名,并在当前目录中查找相应的视图文件 page2.xhtml。
托管 Bean 中的自动导航
在托管 Bean 中定义一个方法以返回视图名称。
@ManagedBean(name = "navigationController", eager = true) @RequestScoped public class NavigationController implements Serializable { public String moveToPage1() { return "page1"; } }
使用托管 bean 获取任何 JSF UI 组件的操作属性中的视图名称。
<h:form> <h3> Using Managed Bean</h3> <h:commandButton action = "#{navigationController.moveToPage1}" value = "Page1" /glt; </h:form>
此处,当单击 Page1 按钮时,JSF 将解析视图名称 page1 作为 page1.xhtml 扩展名,并在当前目录中找到相应的视图文件 page1.xhtml。
条件导航
使用托管 bean,我们可以非常轻松地控制导航。查看托管 bean 中的以下代码。
@ManagedBean(name = "navigationController", eager = true) @RequestScoped public class NavigationController implements Serializable { //this managed property will read value from request parameter pageId @ManagedProperty(value = "#{param.pageId}") private String pageId; //condional navigation based on pageId //if pageId is 1 show page1.xhtml, //if pageId is 2 show page2.xhtml //else show home.xhtml public String showPage() { if(pageId == null) { return "home"; } if(pageId.equals("1")) { return "page1"; }else if(pageId.equals("2")) { return "page2"; }else { return "home"; } } }
在 JSF UI 组件中将 pageId 作为请求参数传递。
<h:form> <h:commandLink action = "#{navigationController.showPage}" value = "Page1"> <f:param name = "pageId" value = "1" /> </h:commandLink> <h:commandLink action = "#{navigationController.showPage}" value = "Page2"> <f:param name = "pageId" value = "2" /> </h:commandLink> <h:commandLink action = "#{navigationController.showPage}" value = "Home"> <f:param name = "pageId" value = "3" /> </h:commandLink> </h:form>
此处,单击"Page1"按钮时。
JSF 将创建一个带有参数 pageId = 1 的请求
然后 JSF 将此参数传递给 navigationController 的托管属性 pageId
现在调用 navigationController.showPage(),在检查 pageId 后,它将返回作为 page1 的视图
JSF 将解析视图名称 page1 作为 page1.xhtml 扩展名
在当前目录中查找相应的视图文件 page1.xhtml
基于 from-action 解析导航
即使托管 bean 的不同方法返回相同的视图,JSF 也提供导航解析选项名称。
查看托管 bean 中的以下代码。
public String processPage1() { return "page"; } public String processPage2() { return "page"; }
要解析视图,请在 faces-config.xml
中定义以下导航规则<navigation-rule> <from-view-id>home.xhtml</from-view-id> <navigation-case> <from-action>#{navigationController.processPage1}</from-action> <from-outcome>page</from-outcome> <to-view-id>page1.jsf</to-view-id> </navigation-case> <navigation-case> <from-action>#{navigationController.processPage2}</from-action> <from-outcome>page</from-outcome> <to-view-id>page2.jsf</to-view-id> </navigation-case> </navigation-rule>
此处,单击 Page1 按钮时 −
navigationController.processPage1() 被调用,它将返回作为页面的视图
JSF 将解析视图名称,page1 因为视图名称是 page,faces-config 中的 from-action 是 navigationController.processPage1
在当前目录中查找相应的视图文件 page1.xhtml
转发与重定向
JSF 默认在导航到另一个页面时执行服务器页面转发,应用程序的 URL 不会改变。
要启用页面重定向,请附加faces-redirect=true 在视图名称的末尾。
<h:form> <h3>Forward</h3> <h:commandButton action = "page1" value = "Page1" /> <h3>Redirect</h3> <h:commandButton action = "page1?faces-redirect = true" value = "Page1" /> </h:form>
此处,单击 Forward 下的 Page1 按钮时,您将获得以下结果。
此处,单击 Redirect 下的 Page1 按钮时,您将获得以下结果。
示例应用程序
让我们创建一个测试 JSF 应用程序来测试上述所有导航示例。
步骤 | 描述 |
---|---|
1 | 在 com.tutorialspoint.test 包下创建一个名为 helloworld 的项目,如 JSF - 创建应用程序 一章中所述。 |
2 | 在 com.tutorialspoint.test 包下创建 NavigationController.java,如下所述。 |
3 | 在 WEB-INF 文件夹下创建 faces-config.xml 并更新其内容如下所述。 |
4 | 如下所述,更新 WEB-INF 文件夹下的 web.xml。 |
5 | 如下所述,创建 page1.xhtml 和 page2.xhtml 并修改 webapp 文件夹下的 home.xhtml。 |
6 | 编译并运行应用程序以确保业务逻辑按要求运行。 |
7 | 最后,以 war 文件的形式构建应用程序并将其部署在 Apache Tomcat Web 服务器中。 |
8 | 按照最后一步中的说明,使用适当的 URL 启动您的 Web 应用程序。 |
NavigationController.java
package com.tutorialspoint.test; import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.RequestScoped; @ManagedBean(name = "navigationController", eager = true) @RequestScoped public class NavigationController implements Serializable { private static final long serialVersionUID = 1L; @ManagedProperty(value = "#{param.pageId}") private String pageId; public String moveToPage1() { return "page1"; } public String moveToPage2() { return "page2"; } public String moveToHomePage() { return "home"; } public String processPage1() { return "page"; } public String processPage2() { return "page"; } public String showPage() { if(pageId == null) { return "home"; } if(pageId.equals("1")) { return "page1"; }else if(pageId.equals("2")) { return "page2"; }else { return "home"; } } public String getPageId() { return pageId; } public void setPageId(String pageId) { this.pageId = pageId; } }
faces-config.xml
<?xml version = "1.0" encoding = "UTF-8"?> <faces-config xmlns = "http://java.sun.com/xml/ns/javaee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version = "2.0"> <navigation-rule> <from-view-id>home.xhtml</from-view-id> <navigation-case> <from-action>#{navigationController.processPage1}</from-action> <from-outcome>page</from-outcome> <to-view-id>page1.jsf</to-view-id> </navigation-case> <navigation-case> <from-action>#{navigationController.processPage2}</from-action> <from-outcome>page</from-outcome> <to-view-id>page2.jsf</to-view-id> </navigation-case> </navigation-rule> </faces-config>
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <context-param> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value>/WEB-INF/faces-config.xml</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> </web-app>
page1.xhtml
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html"> <h:body> <h2>This is Page1</h2> <h:form> <h:commandButton action = "home?faces-redirect = true" value = "Back To Home Page" /> </h:form> </h:body> </html>
page2.xhtml
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html"> <h:body> <h2>This is Page2</h2> <h:form> <h:commandButton action = "home?faces-redirect = true" value = "Back To Home Page" /> </h:form> </h:body> </html>
home.xhtml
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:f = "http://java.sun.com/jsf/core" xmlns:h = "http://java.sun.com/jsf/html"> <h:body> <h2>Implicit Navigation</h2> <hr /> <h:form> <h3>Using Managed Bean</h3> <h:commandButton action = "#{navigationController.moveToPage1}" value = "Page1" /> <h3>Using JSF outcome</h3> <h:commandButton action = "page2" value = "Page2" /> </h:form> <br/> <h2>Conditional Navigation</h2> <hr /> <h:form> <h:commandLink action = "#{navigationController.showPage}" value="Page1"> <f:param name = "pageId" value = "1" /> </h:commandLink> <h:commandLink action = "#{navigationController.showPage}" value="Page2"> <f:param name = "pageId" value = "2" /> </h:commandLink> <h:commandLink action = "#{navigationController.showPage}" value = "Home"> <f:param name = "pageId" value = "3" /> </h:commandLink> </h:form> <br/> <h2>"From Action" Navigation</h2> <hr /> <h:form> <h:commandLink action = "#{navigationController.processPage1}" value = "Page1" /> <h:commandLink action = "#{navigationController.processPage2}" value = "Page2" /> </h:form> <br/> <h2>Forward vs Redirection Navigation</h2> <hr /> <h:form> <h3>Forward</h3> <h:commandButton action = "page1" value = "Page1" /> <h3>Redirect</h3> <h:commandButton action = "page1?faces-redirect = true" value = "Page1" /> </h:form> </h:body> </html>
完成所有更改后,让我们像在 JSF - 创建应用程序一章中一样编译并运行应用程序。如果您的应用程序一切正常,这将产生以下结果。