一、页面组件定义方式
1.在模板(tml)文件中明确定义
<t:textfield t:value="message"/>
这种方式不能在Dreamweaver中预览。
2.在模板文件中隐示定义
<input type="text" t:type="textfield" t:value="message"/>
<a href="#" t:type="PageLink" t:page="Another">Go to Another page</a>
3.在页面类中定义
(1)tml中为:
<a href="#" t:id="theLink">Go to Another page</a>
<input type="text" t:id="theTextBox"/>
(2)在类文件中用annotations来明确组件
@Component(parameters = {"page=Another"})
private PageLink theLink;
@Component(parameters = {"value=message"})
private TextField theTextBox;
二、页面间传值
假定要将一个字串传给Another页面,Another定义如下:
public class Another{
private String passedMessage;
public String getPassedMessage(){
return passedMessage;
}
public void setPassedMessage(String passedMessage){
this.passedMessage = passedMessage;
}
}
1.简单传值方式
@InjectPage
private Another another;
@OnEvent(value="submit", component="userInputForm")
Object onFormSubmit(){
another.setPassedMessage(message);
return another;
}
运行正常,但当浏览器重新请求页面时,传递的数据将丢失。因为Tapestry页面池在更新Another实例时,它不知道你有数据要传到这个页面。
2.将属性域持久化
@Persist
private String passedMessage;
这种方式最简单,它将把我们传给persistent property中的值,存储在HttpSession中。这种方式有副作用,一是大量用户同时访问时占内存,二是Session到期失效。另外每次请求这个页面,Tapestry都会put the value stored for it in the session into that property,no matter what instance of the page
is being used。
3.使用page activation context
这是Tapestry5专门定义的页面传值方式。增加方法onActivate和onPassivate,它们将在Http请求生命期中的一个适当时候被Tapestry调用。
/*The onActivate method is invoked every time the page is loaded
*it might be to check whether the user who tries to access the page *was successfully authenticated
*/
void onActivate(String message){
System.out.println("Another page is activated! The message is: " + message);
this.passedMessage = message;
}
String onPassivate(){
System.out.println("Another page is passivated...");
return passedMessage;
}
在第一个页面实例放入到页面池之前,Tapesty将检查页面是否使用了activation context(the activation context by implementing the pair of methods, onActivate and onPassivate),如果用了,就调用页面实例的onPassivate方法。
Tapestry将记住onPassivate的返回值,并立刻使用页面的另一个新实例,将记录下的值作为参数传递给新实例的onActivate方法。这样就达到了传值目的。
这种方式不用将值存在Session中,而是记录在URL中的。如:http://localhost:8080/t5first/another/hi+there%21
(The message was recorded into the URL while redirecting the user's browser)
三、Application State Object
在Tapestry中,应用程序的每个页面可以使用的对象被称为Application State Object (ASO)。通常,这些是有特殊使用目的的数据对象。假如定义了一个User类:
public class User{
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getLastName(){
return lastName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
}
1.create a private field of the type User and mark it with the @ApplicationState annotation,如在登录页面定义后,在成功登录时写入相应的人员信息。
@ApplicationState
private User user;
Tapestry将在第一次请求ASO时,创建此ASO的实例。也就是说无论什么时候请求ASO,他将一直存在,不为空。
默认情况下,Application State Objects 存储在Session中。这就意味着,如果session还不存在,那么当第一次请求ASO时,它才会被创建。
2.在页面中使用
各个页面可以定义不同的private域,它们都指向同一个Application State Object。
@ApplicationState
private User currentUser;
public User getCurrentUser(){
return currentUser;
}
<p>The user is ${currentUser.firstName} ${currentUser.lastName}</p>
3.检查ASO是否已经存在
定义一个boolean类型的ASO域,它的名称为ASO域加Exists组成。一旦有请求ASO,它将被Tapestry实例化。这个boolean域被置为true,在这之前为false。以user为例:
private boolean userExists;
public boolean getUserExists(){
return userExists;
}
<t:if t:test="userExists">
<p>The user is ${user.firstName} ${user.lastName}</p>
</t:if>
四、Prefixes: prop and literal
a component's properties can have either a prop or literal default prefix. Say, the label property of the TextField component has the default prefix literal, while the value property of the same component has the default prefix prop.
t:label="User Name"与t:label="literal:User Name"等价。
t:label="prop:theLabel"
In this case Tapestry will look for the getTheLabel method in the page class and use whatever that method returns as the label.