页面跳转类组件:ActionLink, DirectLink, ExternalLink, GenericLink, ServiceLink(引用)

新一篇: 4-Oracle积累 | 旧一篇: 0-积累

1-ActionLink组件

暂时理解为,不转向下一页面,只是激活一个监听方法。

页面响应时,创建了一个链接。如果触发了链接时,组件ActionLink得到一个监听器(通过调用方法actionTriggered())。
2-DirectLink组件

-------------------------------------------------------------------------------------------------------------------

1-DirectLink创建一个<a/>标签,该链接包含了一些提供给组件监听方法的上下文环境数据,它被用在当ActionLink不好用的时候。

2-parameters参数指明了一个对象数组,被编码到url上面,当链接被触发的时候,这些对象将会被解码。意思就是可以将“对象”做为参数传递。

监听方法可以通过3种方法取得参数:

1-istenerMethod(parameters) :就是在监听方法中,提供参数

2-istenerMethod(IRequestCycle cycle, parameters)

3- listenerMethod(IReuqestCycle cycle), using IRequestCycle.getServiceParameters()

3-stateful参数为true的时候,当链接被激活的时候,会检查有没有合法的HttpSession如果不能拿到就会抛出StaleLinkException异常。
我不知道你是否觉得有些特别:Tapestry能够将对象通过URL进行页面之间的传递,或者将一个对象完整地保存到客户端的浏览器上。我以前做的项目里面,传递的URL甚至长达一千多个字符。
回想一下在JSP里面,页面与页面之间参数的传递,全部都是String类型的,除非你放在Session中进行传递。而Tapestry却可以传递对象。为什么呢?
其实原因很简单,正如同你先前看见的错误:Could not find an adaptor for class com.ramon.test.MyObj。也就是说,Tapestry仍然是传递String类型的参数,保存在客户端浏览器上的也仍然是 String。作为一个框架,Tapestry将你需要传递的对象转换了一遍,也就是说,通过一个“适配器(adaptor)”,在服务器端将一个对象转 换为一段唯一的String,放到客户端浏览器上,当从客户端将这段String字符串返回到服务器段的时候,Tapestry又会将其还原为原先的对 象,并保留了该对象的状态。
而你提到的“为什么DirectLink并没有提到序列化?”,因为序列化的目的就是为了在数据传输过程中保存对象的状态。序列化是一门非常庞大的学问,当然,也可以简单地片面解释为数据传输的一种规范。既然作为一种规范,有时候可能也就忽略不提了。
关于Tapestry的这个adaptor,在Tapestry4.0中,就可以按照自己的逻辑对官方提供adaptor进行重构。记得大概在 Tapestry4.0-beta5之前,官方没有为T4提供adaptor,那个时候,在Tapestry的官方邮件列表里面,达人们就自己实现 adaptor。

persit="client" 是否要谨慎使用,虽然用起来很爽
我个人觉得对于大对象,是不合适的。该page中的XXXXLink都会有一个参数state:PageName=xxxxxxxx(非常长)。我碰到的问题是,因为GET方式对URL长度的限制,加了那些参数的链接是打不开的。
可能可以用其他方式来避免。但是我觉得最好是小对象,比如个把ID的传输还是很合适的。

实际上你多虑了,你可以仔细看看页面运行的源代码,如果是xxxLink,都是以post方式传递的。下面是我以前在T3时代用DirectLink的一个URL。
是我们【成都建信】www.cdcin.com实际在运行的项目中的一个链接。用word进行数字统计:741 ,当然,这并不是我们最长的链接。
http://www.cdcin.com/Work_safety_constructionFinishForm.html?sp=OH4sIAAAAAAAAAFvzloG1uIhBKTk_Vy85JTe5WC8_US8pX885P6-4pKg0uSQzP88tMy-zOONyjYkuy7Y_B5kYGCqKGLTRNSQlFqfqOQEJTJ3f_X1PPloh08DEwOnJwJGRWJzhnJ-S6sPAHZ-YnJxaUOKSWJJawiDgk5VYlqhfWpKZow8SsQYrKCjJLClNSfXLL2EQgijIScxL1w8uKcrMSwcq4YsHOiQ3s8Q5P7cgMa-ykKGOgdmHQQQoinAFqhx7fFpmDtBAKJc5PjOlhEEYyWzPvJLU9NQioOE88QVF-VmpySWOKSlFUPVwMb_E3FSwWEVBAwMDAzAQeUFm6BUX5uiB3C_yyy3D3jRtOiS8-MByIM-BJTOyGhm9I0skmYGSBeUcQP3_HeatYKgoYeA0MjAwNjSwMDQtYVB81jHhZfPepzuanq9Z87R19dPdu56vnfh0-9LnK7qftq552r-jhEEdqqZ31vOJ85517H86Z8OTXcuf7ml42j_x2ZzOlzMnwFSCTDYxNDCxsAC6VRDsHpB_9aD-FXq0YMn3xnYLJgZGTwbWssSc0lSguwUQ6vxKc5NSi9rWTJXlnvKgG-StAgYGxuvAiHk5d9LzfV1Plyx_2TjZ0MDwaf_2EgZZiIsgzn_RtfHp7LVPdnQ-mzPfGCQPABoE4-93AgAA
虽然这个链接中没有state数据,但是至少可以证明,URL是可以很长的。
那么你所说的GET方式,也就是以Form形式提交的时候。而此时persist的state数据,是以表单的一个hidden放在Form中的。
因此,我认为不会存在你所提的这种情况。

--------------------------------------------------------------------------------------------------------------------

DirectLink组件涉及到session,与ExternalLink组件的区别有两个:

第一: DirectLink涉及session,DirectLink拥有一个boolean类型的stateful参数来选择stateful或stateless,该参数默认为true,即stateful。

而ExternalLink却不涉及session,ExternalLink仅仅是stateless,不能够选择。

第二:非常重要的是,DirectLink与ExternalLink参数传递方式不一样。

DirectLink---->在本页面的监听方法中获取参数,然后将参数设置到下一个页面。

ExternalLink---->通过在下一个页面实现IExternalPage接口以及activateExternalPage方法“接收”参数。

  为了实现分页功能,我们使用DirectLink组件实现。在下面的例子,每个页面我们只显示10条数据,那么HQL就只从数据库中查询出10条数据。对于页面来说,就需要实现“下一页”(或“上一页”)页面跳转,以及向我们的业务逻辑层方法传递分页参数(即当前页码,以及每页显示数据数)。
请看对应的HTML文件中相关代码:
   <span jwcid="@Conditional" condition="ognl:firstDisable">
         <span jwcid="first">首页</span>
         <span jwcid="previous">上一页</span>
</span>
第 <span jwcid="@Insert" value="ognl:pageNo" /> 页
<span jwcid="@Conditional" condition="ognl:lastDisable">
         <span jwcid="next">下一页</span>
         <span jwcid="last">尾页</span>
   </span>
共 <span jwcid="@Insert" value="ognl:total" /> 页
在page文件中声明相关组件:

需要在包含该链接的页面类中定义first previous next maxResult的getter和setter

<component id="first" type="DirectLink">
   <binding name="listener" expression="listeners.changePage"/>
   <binding name="parameters" expression="new java.lang.Object[]{first,maxResult}"/>
</component>
<component id="previous" type="DirectLink">
   <binding name="listener" expression="listeners.changePage"/>
   <binding name="parameters" expression="new java.lang.Object[]{previous, maxResult}"/>
   <binding name="disabled" expression="previousDisable"/>
</component>
<component id="next" type="DirectLink">
   <binding name="listener" expression="listeners.changePage"/>
   <binding name="parameters" expression="new java.lang.Object[]{next, maxResult}"/>
   <binding name="disabled" expression="nextDisable"/>
</component>
<component id="last" type="DirectLink">
   <binding name="listener" expression="listeners.changePage"/>
   <binding name="parameters" expression="new java.lang.Object[]{last,maxResult}"/>
</component>
DirectLink组件表现为一个HTML<a>元素,用来提供一个URL,当用户点击时,触发页面中一个特定的监听方法。
  在实现分页页面跳转的四个组件里,都声明为同一个listener监听方法。请看相应java中的对应监听方法changePage的代码:
public void changePage(IRequestCycle cycle) {
//Tapestry4.0已经deprecated了cycle.getListenerParameters()
   Object[] parameters = cycle.getServiceParameters();
   //获取当前页码
   Integer ig1 = (Integer) parameters[0];
   int i1 = ig1.intValue();
   setPageNo(i1);
   //获取每页最大显示数目
   Integer ig2 = (Integer) parameters[1];
   int i2 = ig2.intValue();
   setMaxResult(i2);
}
  对于DirectLink,parameters参数的赋值方式于ExternalLink一样。这里获取的是一个数组,这个数组包含了两样信息:即将跳转的页码数,以及即将跳转的页面显示多少条数据。
在 前面,我们提到过,页面的java文件在完成页面表现所需数据的处理后,应该将其所有成员变量(页面property)还原为初始值。所以,“当前页码” 以及“每页最大显示数据”这两个数据,我们将它们“保存”在页面上。当点击触发监听方法后,再由页面来提供下一个页面的“页码”和“每页最大显示数目”。 然后再查询新的maxResult条数据。
运行效果图如下:
3-ExternalLink组件

-----------------------------------------------------------------------------------------------------------------------------------------------
ExternalLink对于参数是采用“接收”的方式是指向本应用页面的Link。
ExternalLink组件不会验证用户session,因此ExternalLink组件生成的URL能够被用户收藏,以便再次访问。

<a href="#" 
jwcid="@ExternalLink"
page="ViewArticle"
parameters="ognl:{articleId, 'de'}"
disabled="ognl:languageCode=='de'"
>view this article in German</a>

<div jwcid="@Insert" value="ognl:content">content of the article</div>
package com.myexample;

import org.apache.tapestry.IExternalPage;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.html.BasePage;

public abstract class ViewArticle extends BasePage
implements IExternalPage {

public abstract Integer getArticleId();
public abstract void setArticleId(Integer articleId);
public abstract String getLanguageCode();
public abstract void setLanguageCode(String language);

public void activateExternalPage(Object[] params, IRequestCycle cycle) {
setArticleId((Integer) params[0]);
setLanguageCode((String) params[1]);
}

public String getContent() {
// retrieve the content of the article for the selected language

}

}
-----------------------------------------------------------------------------------------------------------------------------------------------

ExternalLink组件使用的是Tapestry的9种service中的external service。该组件使用External Service 创建继承了IExternalPage接口的一个链接。下面用一个例子说明它的用法。
<a jwcid="@ExternalLink" page="SuccessPage" parameters='ognl:new java.lang.Object[]{"This is Success Page!", item.id}'disabled="ognl:item.Isable"></a>
page="SuccessPage"这个参数的作用,就是指定了将要跳转的页面名称,ExternalLink组件的page参数根据配置文件tapestry.application文件中的配置找到对应的page文件:
<page name="SuccessPage" specification-path="/WEBINF/SuccessPage.page"/>
然后在SuccessPage.page文件中,根据:
<page-specification class="com.ce.tapestry.Success">
找到对应的Success.java文件。在Success.java文件中,我们发现该类继承了IExternalPage接口:
public abstract class Success implements IExternalPage
以及实现了activateExternalPage(Object[],IRequestCycle)方法。
对于ExternalLink组件,它必须继承IExternalPage接口,并实现public void activateExternalPage(Object[] parameters,IRequestCycle cycle)方法。该方法的参数Object[]来自该组件的parameters参数的值。 disabled参数默认为false,当为true时,不能被“点击”。
4-GenericLink组件

组件GenericLink通常用于跳转到应用程序范围以外的链接。 虽然GenericLink可以用其他组件也能完成,但是GenericLink更灵活:它可以设置为disabled,象DirectLink或者ActionLink一样也能包含Rollover组件。
使用方法如下:
<a jwcid="@GenericLink" href="ognl:item.homepage" disabled="false"/>
Href参数:其作用很明显,就是提供一个链接地址。从上例可知:从item.homepage取出地址。
disabled参数:该参数默认为false,当为true时,不能被“点击”。关于disabled参数,所有link类组件都有,作用均相同。
5-PageLink组件

相当于不带参数的ExternalLink。

PageLink组件非常简单,只需要在page参数中指明需要跳转到下一个页面的名字。不过需要注意的是,PageLink和ExternalLink使用的不是同一个service,该组件使用了Page Service创建了另外一个链接URL。
使用方法请见例子:
<a jwcid="@PageLink" page="Infos"><img src="images/lyb.gif" width="50" height="18" border="0">
</a>
跳转到以下的URL:http://localhost:8080/hello/helloworld?service=page/Upload
6-ServiceLink组件

创建任意不带有参数的引擎服务,ServiceLink组件用法与ActionLink,PageLink和DirectLink等组件相似,但常常与具体的应用服务一起使用。Service参数是要调用的EngineService对象的名称。(Body)

以上的Link类组件,都需要在Body组件范围内使用。

posted @ 2008-12-02 15:51  俩醒叁醉  阅读(1959)  评论(1编辑  收藏  举报