JSF - 页面导航

导航规则是 JSF 框架提供的规则,用于描述单击按钮或链接时要显示哪个视图。

导航规则可以在名为 faces-config.xml 的 JSF 配置文件中定义。它们可以在托管 bean 中定义。

导航规则可以包含显示结果视图所基于的条件。JSF 2.0 也提供了隐式导航,无需定义导航规则。

隐式导航

JSF 2.0 提供了名为隐式导航自动视图页面解析器机制。在这种情况下,您只需将视图名称放在操作属性中,JSF 就会在部署的应用程序中自动搜索正确的 视图 页面。

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

JSF Page 2

托管 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

JSF Page 1

条件导航

使用托管 bean,我们可以非常轻松地控制导航。查看托管 bean 中的以下代码。

JSF 条件导航

@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

JSF Page 1

基于 from-action 解析导航

即使托管 bean 的不同方法返回相同的视图,JSF 也提供导航解析选项名称。

JSF From Action

查看托管 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 Page 1

转发与重定向

JSF 默认在导航到另一个页面时执行服务器页面转发,应用程序的 URL 不会改变。

要启用页面重定向,请附加faces-redirect=true 在视图名称的末尾。

JSF Forward vs Redirect
<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 按钮时,您将获得以下结果。

JSF Page 1 Forward

此处,单击 Redirect 下的 Page1 按钮时,您将获得以下结果。

JSF Page 1 Redirect

示例应用程序

让我们创建一个测试 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.xhtmlpage2.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 - 创建应用程序一章中一样编译并运行应用程序。如果您的应用程序一切正常,这将产生以下结果。

JSF 导航