1. JSF上支持从一个页面到另一页面,与Struts 中的ActionForward有点相似,JSF称之为导航系统(JSF navigation system.) ,控制这种页面与页面之间联系的一个重要的部件是导航控制者(navigation handler),它的职责就是判断下一步应该加载那一个页面.这本书中主要描述的是默认的导航控制者(以下简称为handler)的处理特点.(当然这个handler是可以改变的).
2. 原文:(The navigation handler operates in response to action events,3 which are usually executed by
action sources (components that capture user gestures, like buttons or hyperlinks).用户点击组件(像按钮和可以触发事件的链接),这些组件产生事件,事件被相应的方法(这里指的是action method)处理后,action method后返回一个String 字符串(outcome),然后handler根据这个string返回值(logical outcome或者是hardcoded outcome--硬编码的值),去到配置文件找这个返回字符串对应的页面,然后把这个页面展现.这里只是简单的概述了一下,实际上的操作会有点复杂,下面会做具体的分析.
3. 原文:(The navigation handler operates on a set of navigation rules, which define all of the application’s possible navigation paths. A navigation rule specifies which pages can be selected from a specific page or set of pages. Each path to a page is represented by a single navigation case. The navigation case is selected based on logical outcome (retrieved from the component itself or its associated action method) and/or the expression for the executed action method itself.)
handler要处理很多的导航规则(navigation rule),这些规则就是指定从那一个页面或者是那一些页面(通过类似于与正则表达式的方式)可以去到某一个特定的页面.这种从一个页面到一个页面是通过配置一个导航示例(navigation case )来实现的,具体选择那一个导航示例,是由一个outcome值来决定的.
4.下面是一个导航的示例图:
这个配置文件中涉及到了三个页面:PlaceOrder.jsp, ConfirmOrder.jsp, and OrderEntry.jsp.
- 从PlaceOrder.jsp去到的页面会有两种情况(case),当outcome为"success"时,去到的是ConfirmOrder.jsp这个页面,当outcome为"failure"时去到的页面是OrderEntry.jsp这个页面.
- OrderError.jsp也有一个导航规则(navigation rule)当outcome为"retry"时去到页面是PlaceOrder.jsp
- 这里对于ConfirmOrder.jsp这个页面没有导航规则,也就是说从ConfirmOrder.jsp不会去到任何页面.
5. 上面示例的.xml配置文件的代码为:
< navigation-rule >
< from-view-id > /OrderError.jsp </ from-view-id >
< navigation-case >
< from-outcome > retry </ from-outcome >
< to-view-id > /PlaceOrder.jsp </ to-view-id >
</ navigation-case >
</ navigation-rule >
< navigation-rule >
< from-view-id > /PlaceOrder.jsp </ from-view-id >
< navigation-case >
< from-outcome > success </ from-outcome >
< to-view-id > /ConfirmOrder.jsp </ to-view-id >
</ navigation-case >
< navigation-case >
< from-outcome > failure </ from-outcome >
< to-view-id > /OrderError.jsp </ to-view-id >
< redirect />
</ navigation-case >
</ navigation-rule >
6. 导航规则的.xml文件中元素项的示意图:
Figure 3.14
Navigation consists of navigation rules, which are defined with the <navigation-rule> element in a JSF configuration file. Optionally, a <navigation-rule> can specify the page to which it applies with the <from-view-id> element. Each <navigation-rule> has one or more <navigation-case> elements, which must have a <to-view-id> element that specifies the next page to load. A <navigation-case> can optionally specify an outcome with a <from-outcome> element and an action with the <from-action> element. If the <redirect> element is
specified, JSF will send an HTTP redirect instead of forwarding to the view internally. Both the <navigation-rule> and <navigation-case> elements can optionally have <description>, <display-name>, and <icon> elements which are generally used for tools.
7. 具体的规则:
- 一个navigation rule下可以包含多个navigation case,表示从一个页面可以跳转到的页面有多少种可能.
- <from-view-id> 指的是从那一个页面接受的用户请求,内容为页面的地址或者为页面的名称(包含一个相对路径的值)
- <to-view-id> 表明的去向的页面的地址或名称.
- <from-view-id>和<to-view-id>可以指向的是任何的页面或资源,必须以"/"开头,而且包含相对于应用的根目录的地址(it must be relative to the web application’s root directory and prefixed with a slash (/).)
- 当<navigation-case>中指定了<redirect>值时,是告诉JSF redirect这个请求到相应的地址去.这时用户看到它的页面展示地址变了,不再是请求的那个地址.
- 对于一些通用的outcome值没有必要再指定其它的一些页面,比如当outcome这个返回值为"login","logout"等,
8. outcome值是从何处来?这里重点说一下这个判断执行那个navigation case的根据,因为刚开始学习JSF的navigation 的时候,对于这个outcome总会让人分不清.
- outcome 值可以由组件中的 action属性来决定.
- 组件中的action属性可以有两种写法,一种是直接写一个字符串,比如上面例子中的由/OrderError.jsp页面到/PlaceOrder.jsp的组件代码就为:
< h:commandButton value = " Retry order submission " action = " retry " />
- 另一种方法是配置组件的action属性到一个方法,具体的outcome值由应用执行完这个action method后来决定返回的值是什么,就像PlaceOrder.jsp页面上的组件的代码这样:
< h:commandButton value = " Place Order " action = " #{orderManager.placeOrder} " />
- 当组件中不设置action 属性的时候也是可以在.xml配置文件中指定产生outcome值的方法的,这就是<from-action>要做的.就像这样: <navigation-case>
<from-action>#{orderManager.placeOrder}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/ConfirmOrder.jsp</to-view-id>
</navigation-case>,只有从orderManager中placeOrder方法过来,而且outcome值为"success"才执行这个case.如果把<from-outcome>success</from-outcome>去掉,则说明只要是从orderManager中placeOrder方法过来的就到>/ConfirmOrder.jsp去,不管outcome的值是多少,是null也罢. - <from-view-id>中的值可以用匹配的方式来指定:
< navigation - rule >
< from - view - id >/ corporate /**/ /*</from-view-id>或者<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>about</from-outcome>
<to-view-id>/corporate/about.html</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>contact info</from-outcome>
<to-view-id>/corporate/contact.html</to-view-id>
</navigation-case>
</navigation-rule>
- 最后要说的是组件中的action 属性和 actionListener属性,区别主要在于action 是用来做导航(navigation)的,而actionlistener是指用户产生一个行为的时候(点击按钮等)这个按钮要触发的方法.