Tapestry最新版5.1.0.5教程(三)
Posted on 2009-06-05 14:24 云自無心水自閑 閱讀(2731) 評論(0) 編輯 收藏 所屬分類: Java 、心得體會 、Tapestry在講述頁面之間傳遞值之前首先要介紹一個Tapestry的頁面緩存。
Tapestry的一個經常被提及的就是頁面的緩存,Wicket也有頁面緩存,但是Wicket的頁面是緩存在Session里的,缺省好像是只緩存5個頁面。這一點讓我對Wicket的印象打了折扣,首先,這種機制在高并發,也就是多人同時在線的時候,感覺頁面緩存會占用大量資源。而Tapestry的頁面緩存是在一個大池中。
頁面緩存的優點就是提高效率,但是缺點也是比較明顯的,那就是給開發實現帶來了不方便。我覺得眾人說的Tapestry的學習曲線比較陡,一部分原因就在這里。上一章講過,在Tapestry中,頁面的跳轉是通過InjectPage實現的。Tapestry在頁面跳轉時,會從緩存池中選取一個相應頁面的實例,渲染成html。關鍵在于Tapestry在把頁面放到緩存池之前,會把頁面實例里的值清空。這就是造成頁面傳值麻煩的原因。寫段代碼示例:
Class Register {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Class Start{
@InjectPage
private Register register;
Object onSubmit() {
register.setName("superman");
return register;
}
}
如果頁面從Start跳轉到Register,并且希望把superman這個值傳遞給Register這個頁面,感覺上只要象上面這段代碼一樣簡單設置一下就行了,但是實際上這樣是無法在Register的頁面上顯示出superman這個名字的。因為Tapestry會在頁面顯示時候的時候,從緩存池中提取一個實例,這個實例在放入緩存池之前,name屬性的值就被清空了。
下面是Tapestry頁面之間傳遞值的幾種方式:
2、Persist。最簡單的方式是使用persist注解。
Class Register {
@Persist
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
只要這樣指定后,Tapestry會把name的值保存在Session中,以備下次使用。但是這樣的缺點也很明顯,首先是占用資源,另外這樣的URL是不能作為書簽的,因為參數值不體現在URL中,而是保存在Session中。
3、Page Active Context。這個方法比較好,但是需要一些代碼來實現。主要是添加兩個函數onActivate和onPassivate。
Class Register {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
void onActivate(String name) {
this.name = name;
}
String onPassivate() {
return name;
}
}
在Start頁面中,我們使用了InjectPage把Register注入到了類中,如果只是簡單地返回Register,是不能正確顯示name的值的,但是在Tapestry會在把Start頁面中的Register放回緩存池,清空Register實例中的變量值之前,檢查這個類是否但是現在我們實現了onActivate和onPassivate這兩個方法,Tapestry會自動
4、SessionState
在Tapestry中有一種類型的對象存儲在Session中,所以對所有頁面都是可見的,但是又不需要對頁面暴露Session。在Tapestry5以前,稱之為ApplicationStateObject,但是這個稱呼并不準確,因為這個對象不是Application級別,而只是Session級別,所以Tapestry5開始,改名為SessionStateObject。
使用方法也很簡單,只需要在JavaClass中,給相應的屬性添加一個@SessionState注解即可。
需要提醒注意的是,SessionState區分對象實例不依賴于實例的名稱,而是根據實例的類型,比如:你在一個類中使用@SessionState注解了一個String name;而在另一個類中想再用@SessionState注解一個String password;這是不行的,Tapestry會把這兩個當作同一個對象實例。
另一個需要注意的是,SessionState注解之后,Tapestry會馬上會初始化生成一個該對象的實例。