`
zhangziyangup
  • 浏览: 1074919 次
文章分类
社区版块
存档分类
最新评论

JavaServer Faces 1.2 入门,第 1 部分: 构建基本应用程序(3)

 
阅读更多

JSF 中的导航

JSF 有一个导航机制(与 Struts 相似)。JSF 的导航机制提供逻辑结果,可以将逻辑结果映射到下一个逻辑视图。在本节中,我们将在 Calculator 应用程序中添加导航。

导航规则

图 11 显示将在 Calculator 应用程序中添加的导航规则:


图 11. 在 Calculator 应用程序中添加的导航规则
导航规则

可以用工具帮助布置 Web 应用程序的流程。许多 IDE 提供了用来绘制 JSF 应用程序的导航规则的工具。图 12 显示 Eclipse JEE 中的 Navigation Rule Layout Tool:


图 12. Eclipse 中的导航规则布局
Eclipse 中的导航规则布局

在学完本节之后,图 11 和图 12 的意义就会明确了。

可能不需要导航

有时候需要从一个视图导航到下一个视图。但是,许多 JSF 组件框架有树视图和选项卡视图。一个视图可能有 10 个选项卡,单击一个选项卡就会装载视图的另一个部分。通过使用这种设计,就可以在不编写导航规则的情况下轻松地创建大型应用程序,因为整个应用程序都在一个视图中。这种方法的细节(包括实现方法和最佳实践)超出了本教程的范围。

首先添加一个链接到计算器页面的主页。然后,将计算器页面分割为两个页面:一个页面显示计算器视图,一个页面显示结果视图。还需要通过导航规则在计算器页面、结果页面和主页之间来回移动。

从主页链接到计算器页面

可以通过三种方式从主页链接到计算器页面:

  • 通过一个 commandLink 和一个导航规则
  • 通过一个 commandLink 和一个使用重定向的导航规则
  • 通过一个 outputLink

通过 commandLink 和导航规则进行链接需要在 faces-config.xml 文件中添加一个导航规则,见清单 38:


清单 38. faces-config.xml 中定义的导航规则

<navigation-rule>
<navigation-case>
<from-outcome>CALCULATOR</from-outcome>
<to-view-id>/pages/calculator.jsp</to-view-id>
</navigation-case>
</navigation-rule>

清单 38 声明,返回 CALCULATOR 的任何动作将导致 JSF 装载 /pages/calculator.jsp 作为下一个视图。这个规则是全局的,也就是说,如果在应用程序中任何地方的任何动作返回了 CALCULATOR,就会进入 /pages/calculator.jsp(除非应用了更特定的规则 — 在 JSF 中,可以添加 <from-view-id>,让规则只应用于这个视图;本节后面会讨论更特定的规则。)清单 38 与 Struts 中的全局转发 相似。

然后,添加清单 39 所示的 commandLink,它必须放在 <h:form> 中:


清单 39. 在主页中使用 commandLink

<h:form>
<h:panelGridcolumns="1">
<h:commandLinkaction="CALCULATOR"value="CalculatorApplication"/>
...

这可以实现所需的效果:在浏览器中装载 Calculator 应用程序。但是,尽管显示了计算器视图,而浏览器中的 URL 仍然是 http://localhost:8080/calculator3/home.jsf,这可能让用户觉得困惑。这可能使用户很不安,尤其是熟悉 Web 的用户。另外,用户可能希望用应用程序的计算器部分设置书签,但是他们不知道真正的 URL。

纠正这个问题的一种方法是在 faces-config.xml 导航规则中使用 redirect,见清单 40:


清单 40. 包含 redirect 元素的导航规则

<navigation-rule>
<navigation-case>
<from-outcome>CALCULATOR_REDIRECT</from-outcome>
<to-view-id>/pages/calculator.jsp</to-view-id>
<redirect/><!--LOOKHERE-->
</navigation-case>
</navigation-rule>

commandLink 使用这个导航规则的方法是指定结果字符串作为 action 属性。当用户单击清单 41 中的链接时,用户会进入计算器页面:


清单 41. 使用包含 redirect 元素的导航规则

<h:commandLinkaction="CALCULATOR_REDIRECT"value="CalculatorApplication(redirect)"/>

这解决了上述问题,但是增加了一次服务器访问,这在慢速连接上可能要花费较长时间。但是,如果正在构建内部应用程序,那么这次访问花不了多长时间。

如果不介意直接链接要装载的页面,就不需要两次访问服务器,见清单 42:


清单 42. 用 outputLink 直接链接

<h:outputLinkvalue="pages/calculator.jsf">
<h:outputTextvalue="CalculatorApplication(outputlink)"/>
</h:outputLink>

清单 42 直接链接下一个视图。在 Model 2 体系结构和 JSF 中,从一个视图直接链接下一个视图被认为是一种不好的做法。在通常情况下,控制器应该有机会为下一个视图初始化模型,所以更好的方法是通过动作方法。但是,清单 42 确实创建了一个链接,而且在浏览器中会显示正确的 URL。

无法给 JSF 应用程序加书签一直是个问题。几个框架解决了这个问题,包括 JBoss Seam。JSF 2 也将解决这个小问题。

导航到结果页面

在计算器页面中执行计算之后,下一个视图应该是结果页面。为此,需要添加清单 43 中的导航规则:


清单 43. 从计算器视图中所有动作到结果页面的导航规则

<navigation-rule>
<display-name>CalculatorView</display-name>
<from-view-id>/pages/calculator.jsp</from-view-id>
<navigation-case>
<from-outcome>results</from-outcome>
<to-view-id>/pages/results.jsp</to-view-id>
</navigation-case>
</navigation-rule>

清单 43 声明,如果当前视图是计算器视图(calculator.jsp),而且任何动作返回 results,那么下一个 JSF 视图应该是结果页面(results.jsp)。JSF 查看动作方法的返回值,将它们转换为字符串(如果它们不是 null 的话),然后使用这个字符串选择下一个视图。返回类型可以是任何对象,因为将调用它的 toString 方法。(许多人使用 Enum。)

将所有操作改为返回 results,就像清单 44 中的 add() 方法这样:


清单 44. 动作方法现在返回 results

publicStringadd()...{

FacesContextfacesContext
=FacesContext.getCurrentInstance();

try...{
calculator.add();
facesContext.addMessage(
null,newFacesMessage(
FacesMessage.SEVERITY_INFO,
"Addedsuccessfully",null));

}
catch(Exceptionex)...{
facesContext.addMessage(
null,
newFacesMessage(FacesMessage.SEVERITY_ERROR,ex.getMessage(),null));
}

return"results";
}

注意,add() 方法现在返回 results,而 results 映射到 results.jsp。注意,Cancel 按钮不返回 results。如果一个动作返回的值没有映射到导航规则,JSF 就留在当前视图上。

可以以更特定的方式指定规则,见清单 45:


清单 45. 与动作匹配的映射

<navigation-rule>
<display-name>CalculatorView</display-name>
<from-view-id>/pages/calculator.jsp</from-view-id>
<navigation-case>
<from-action>#{calculatorController.add}</from-action>
<from-outcome>results</from-outcome>
<to-view-id>/pages/results.jsp</to-view-id>
</navigation-case>
</navigation-rule>

但是,现在需要为每个方法设置一个映射。这不符合 DRY 原则。

还希望在计算器页面中添加一个返回主页的 commandButton,见清单 46:


清单 46. 包含返回主页链接的计算器动作

<div>
<h:commandButtonaction="#{calculatorController.add}"value="Add"/>
<h:commandButtonaction="#{calculatorController.multiply}"value="Multiply"/>
<h:commandButtonaction="#{calculatorController.divide}"value="Divide"/>
<h:commandButtonaction="#{calculatorController.clear}"value="Clear"immediate="true"/>
<h:commandButtonaction="HOME"value="Home"immediate="true"/>
</div>

注意,主页链接指定的动作值是 HOME。清单 47 所示的导航规则将主页链接使用的 HOME 值映射到主页:


清单 47. 主页映射导航规则

<navigation-rule>
<navigation-case>
<from-outcome>HOME</from-outcome>
<to-view-id>/home.jsp</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>

注意,commandButtoncommandLink 采用相同的动作处理和导航规则。

结果页面有返回计算器页面和主页的链接,见清单 48:


清单 48. 可以从结果页面返回计算器页面和主页

<h:panelGridcolumns="1"rowClasses="oddRow,evenRow">
<h:commandLinkaction="calculator"value="Returntothecalculatorpage"/>
<h:commandLinkaction="HOME"value="Gotothehomepage"/>
<h:commandLinkaction="calculatorMain"value="Gotomaincalculatorpage"/>
</h:panelGrid>

可以以两种方式返回计算器页面。一种方式与前面看到的相似,见清单 49:


清单 49. 返回计算器页面的映射

<navigation-rule>
<display-name>ResultsPage</display-name>
<from-view-id>/pages/results.jsp</from-view-id>
<navigation-case>
<from-outcome>calculator</from-outcome>
<to-view-id>/pages/calculator.jsp</to-view-id>
</navigation-case>
</navigation-rule>

清单 49 声明,如果当前在结果页面(/pages/results.jsp)上而且一个动作返回 calculator,那么进入计算器页面(/pages/calculator.jsp)。如果不希望采用清单 49 这么特定的方式,也不希望采用全局转发,那么可以使用清单 50:


清单 50. 从 pages/* 下的任何地方返回计算器页面的映射

<navigation-rule>
<from-view-id>/pages/*</from-view-id>
<navigation-case>
<from-outcome>calculatorMain</from-outcome>
<to-view-id>/pages/calculator.jsp</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>

可以使用清单 50 这样的方式定义应用程序中的逻辑区域,并让结果只应用于这些位置。

结束语

本教程讨论了 JSF 并强调它是一个组件模型。因为 JSF 与 Swing、SWT 或 AWT 一样是一个组件框架,它使 Web 应用程序开发更接近传统的 GUI 开发,而不像传统的 Web 开发。与用典型的 Model 2 框架编写的应用程序相比,用 JSF 编写的应用程序更短,更容易理解和维护。因此,Java 社区对 JSF 很有兴趣,围绕 JSF 展开的工作正在不断增加。

正在开发的 JSF 2 将结合一些 Facelets 概念,添加本机 Ajax 支持,并使 JSF 组件开发更加简便。JSF 2 应该会进一步促进开发人员对 JSF 的热情。新的模型能够通过 Ajax 进行部分页面显示,这可以通过 Ajax4JSF 等工具实现。

但是,JSF 并非没有竞争对手。在各种服务器端组件模型中,Tapestry 5 看起来很有潜力,但是它与 Tapestry 4 不兼容。Wicket 也非常有趣,但是还不足以引起许多开发人员的关注。

还有非组件的服务器端 Java 框架。Struts 2.x 已经在改进 WebWork 方面取得了出色的成果,有些人希望 Struts 2.1.x 进一步发展,但是 Struts 2 实际上基于 WebWork 而不是 Struts 1.x。Spring MVC 正在迅速发展,如果您需要使用非 GUI 组件的服务器端 Web 框架,它是不错的选择。

最后,还有将工作委托给服务器上的服务的纯客户端框架,比如 Google Web Toolkit(GWT)和 Adobe Flex。(这种体系结构与 JSF 不一样,但是目标应用程序是相同的。)它们各有优缺点,这可能会影响 JSF 的推广。

但是,JSF 的前景还是不错的,因为它是 Java EE 的标准,而且它背后有一个活跃的社区。业界对 JSF 的期望超过对 Tapestry、Spring MVC、Java Flex 和 GWT 的期望。JSF 2.0 会进一步促进 JSF 的发展。

本教程系列的第 2 部分将讨论 JSF 生命周期、检验器、转换器、阶段监听器和其他高级 JSF 特性。

下载

描述 名字 大小 下载方法 本文的示例代码1
j-jsf1.zip 112KB HTTP
关于下载方法的信息

注意:

  1. 用 Eclipse JEE、Tomcat 和 Maven 2 运行本教程源代码的说明和 JAR 文件见 参考资料

参考资料

学习

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics