浏览 5136 次
锁定老帖子 主题:Tapestry 5 页面导航
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-03-16
Tapestry 5 页面导航
本质上,Tapestry应用是许多相关的工作在一起的页面的集合。从某种程度来说,每一个页面就是一个应用。
任何单个的请求对应一个页面。请求来源于两种形式:
动作请求与呈现请求的划分是Tapestry 5 中新出现的概念,它的某些方面是基于Portlet规范的思想,区分出这两种类型的请求减轻了许多在传统web应用中当用户使用浏览器的后退按钮或点击刷新按钮时的问题。
动作请求
这两种情况,事件处理方法返回的值控制着送往用户端web浏览器的响应。
动作请求的URL包含页面名字、组件的嵌套id和在组件中触发事件的名字(通常是"action")。此外,一个动作请求可以包含额外的上下文信息(context information),以提供给事件处理方法(与方法参数有关)。
这些URL暴露了一些应用的内部结构。随着时间的推移,一个应用在维护中组件的id可能会改变,这就是说动作请求的URL不能被收藏(存为书签)。幸运的是,用户很少有这种机会来改变组件的id(参见下文):
以下是动件请求事件处理方法(动作的监听方法)的不同返回说明。
Null response
如果一个事件处理方法没有返回值或者返回null,此时当前页面(包含该组件的页面)会呈现响应(即响应请求)。
当前页面的页面呈现链接被创建并重定向到客户端。客户端浏览器随后提交的将是一个产生新页面的新请求。用户将会在浏览器看到一个新产生的内容。地址栏里的URL将会是一个呈现请求的URL(render request URL)。呈现请求的URL简短且包含较少的应用结构信息(比如,他不包含组件id和事件类型)。呈现请求URL是可供用户收藏的。动作请求URL是暂时性的,仅当应用处于激活状态时有意义,这并不意味着可以用于随后的session。
String response
当返回一个字符串时,此字符串应该是页面的逻辑名(而非页面的全类名)。另外,页面的名字不区分大小写。
其次,呈现请求的URL被构造并重定向到客户端。
Page response
我们也可以返回一个页面实例,而非一个页面名字。
通常,我们会在页面返回前以某种方式设置页面(举例如下,即对页面属性对象赋值)。
你也可以返回页面内的一个组件,但些时将会产生一个运行时警告。
Link response
Stream response
Object response
事件处理方法返回任何其他对象类型都是错误的。
页面呈现请求(Page Render Requests )
呈现请求在结构与行为上要比动作请求简单。简单情况下,URL仅仅是页面的逻辑名。
页面可以有一个活化上下文(activation context)。活化上下文表现为页面状态的持久化信息。实际上,活化上下文通常是一些数据库持久化对象的id。
当一个页面有活化上下文时,上下文的值被追加到URL路径中。并不是所有的页面都有活化上下文。
当呈现请求链接被创建时,活化上下文可以被显式设值(PageLink组件有一个context参数可以用来设值)。当没有提供显式活化上下文时,页面会自己查找它的活化上下文。
这种查找表现为事件的触发。事件名字为passivate(我们马上会看到它的一个相对应的名字activate)。方法返回的值被用做上下文。
For example:
public class ProductDetail { private Product _product;
. . .
long onPassivate() { return _product.getId(); }
} 活化上下文可以由一连串的值组成,即方法返回的是数组或List列表。
页面激活Page activation
当一个页面呈现请求到来时,页面会在它呈现前被激活。
激活主要为了两个目的:
后者提到的校验,通常涉及到用户标识及访问;如果我们的页面仅允许特定的用户访问,就可以用页面的激活事件来负责这个访问的校验。
一个页面的激活事件处理器(activate event handler)对应着它的钝化事件处理器(passivate handler):
. . .
void onActivate(long productId)
{ _product = _productDAO.getById(productId);
}
. . .
在此相关的部分是:当页面呈现时,它可能包含更多的动作请求URL(链接与表单)。那些链接与表单的动作请求也一样通过激活页面开始,然后再执行其他的操作。这形成了一个不断的包含同样活化上下文请求链。
激活事件处理器(方法)也可以返回一个值,它与动作请求的事件触发器返回的值是一样的。这通常用于访问校验场景。
页面导航模式(Page Navigation Patterns)
动件链接和上下文及页面上下文可以以许多方式组合在一起。
让我们通过一个产品分类页来介绍一个经典的主列表/详细页关系的例子。在这个例子中,ProductListing页面是产品的列表页,ProductDetails页是相应的显示特定产品的详细页。
动作请求/持久化数据
这种模式下,ProductListing页面使用动作事件,ProductDetails页面使用了持久化属性。
ProductListing.html:
<t:loop source="products" value="product">
ProductListing.java:
@InjectPage private ProductDetails _details;
Object onActionFromSelect(long productId)
{ _details.setProductId(productId);
return _details;
} ProductDetails.java:
@Inject private ProductDAO _dao;
private Product _product;
@Persist
private long _productId;
public void setProductId(long productId) { _productId = productId; }
void onActivate()
{ _product = _dao.getById(_productId);
} 以上代码极少,也许对原型来说已经足够好了。
当用户点击一个链接时,动作请求URL起初类似http://.../productlisting.select/99,然后最终的呈现请求的URL将会类似http://.../productdetails。注意产品id("99")并没有显示在呈现请求的URL中。
它还有一些次要的缺点:
动作请求/活化上下文(Action Requests / Persistent Data??)
我们可以使用passivation 和 activation 上下文来避免使用session,使得链接更可收藏,从而在不改变ProductListing页面的情况下改进先前的实例。
ProductDetails.java:
@Inject private ProductDAO _dao;
private Product _product;
private long _productId;
public void setProductId(long productId) { _productId = productId; }
void onActivate(long productId)
{ _productId = productId;
_product = _dao.getById(_productId);
}
long onPassivate() { return _productId; }
此种方法的优点是页面到页面的连接发生在类型安全的Java代码中——ProductListing页面的onActionFromSelect方法。它也有不好的地方就是点击一个链接服务端需要两次往返过程(由两个页面完成这一请求)。
呈现请求一次
这是一件最通用的主列表/详细页的版本。
ProductListing.html:
<t:loop source="products" value="product"> ProductListing.java:
不需要代码来处理链接。
ProductDetails.java:
@Inject private ProductDAO _dao;
private Product _product;
private long _productId;
void onActivate(long productId)
{ _productId = productId;
_product = _dao.getById(_productId);
}
long onPassivate() { return _productId; }
不再需要setProductId()方法。
局限性
随着我们应用流程的扩展,我们可能会发现找不到一个合理的方式去避免在不同的请求间(在页面活化上下文之外)持久化某些数据。比如:如果从ProductDetails页面开始,允许用户导航到相关的一些页面然后又返回到ProductDetails页面,这就开始需要在页面到页面再到页面间保持传递的产品id。
在某些方面,持久化值更有意义。随后,我们将会实现客户端持久化策略(client-side persistence strategy),它将对持久化数据进行编码,如产品id属性将自动的加入到查询参数中(和隐藏的表单域)。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-03-17
good,希望共进步!
|
|
返回顶楼 | |
发表时间:2007-03-19
兄弟,很不错的,继续努力呀!!
|
|
返回顶楼 | |
发表时间:2007-03-20
Great!
学习中... |
|
返回顶楼 | |