能夠保證有效運行的一個非常重要的原因是,用有狀態的javabean代替無狀態的servlet構建一個tapestry應用。page是有狀態的,他只能在一個線程里為一個用戶處理一個 request,而一個servelet,沒有用戶的狀態,可以在并發線程中為任何數量同時發生的request提供服務。使用有狀態的page遇到的問題和使用數據庫的連接遇到的問題非常相似 閱讀全文
2007年1月29日 #
能夠保證有效運行的一個非常重要的原因是,用有狀態的javabean代替無狀態的servlet構建一個tapestry應用。page是有狀態的,他只能在一個線程里為一個用戶處理一個 request,而一個servelet,沒有用戶的狀態,可以在并發線程中為任何數量同時發生的request提供服務。使用有狀態的page遇到的問題和使用數據庫的連接遇到的問題非常相似 閱讀全文
<img jwcid="@Any" src="images/btn2.gif" onClick="ognl:yourScriptFun"/>
a) @Persist("client")
b) @Persist("client:page")
c) @Persist("client:app")
a) is the same as b). If you use b) for a property x for page Foo, then
you can get back the property only if the navigation is Foo => Foo. If the
navigation is Foo => Bar => Foo, then it will be lost when Bar is
invoked. In contrast, if you use c), then it will be maintained all
the way.
client 跟 session是一樣的效果只是實現的方式不一樣, 一個是存在cookie或url中另一個是存在http session中。
client:page session:page 僅在當前頁面有用, 假如轉到其他頁面 這個屬性值就失效了。
client:app session:app 對于整個application都有效, 轉到其他頁面再轉回來的話這個值仍然存在。如果我們想讓他失效怎么辦呢?你可以調用這個方法cycle.forgetPage("YourPageName").
我們來看一下最簡單的TextField組件,組件定義如下 閱讀全文
2. 持有iframe的頁面類中實現一個getIframeRenderer方法: 閱讀全文
I've added a new screencast, this one showing off the use of the tapestry-simple Maven archetype to create a new project. It runs about five minutes and shows off how simple it is to get up and running.
If you haven't built Tapestry 5 locally, you need to remember to add -DremoteRepositories=http://people.apache.org/repo/m2-snapshot-repository/
to the command line.
I'm thinking about starting a vote to do a preview release of Tapestry 5, just to get the necessary JARs and archetypes into the general Maven repository.
顯示不友好的URL等,這些都可以使用redirect-after-postpostredirectredirectredirectPagefriendlyUrlurl
要使用這個模式,不得不提到一個ILinkT4listener:
閱讀全文
閱讀全文
對之前的該文章進行了一些修正,主要是針對finishLoad()方法。
我覺得對初學者會有一些幫助。
下面這幾個函數是我在使用的,它們的執行順序依次從上到下。
1.protected void finishLoad() {} ***
2.public void pageValidate(PageEvent event) {}
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {}
4.public void pageBeginRender(PageEvent event) {}
// 如果有表單提交,則將form中的各字段的值賦給頁面類
5. ...... 賦值
6.public void submit() // 表單提交等用listenter:調用的方法
7.protected void prepareForRender(IRequestCycle cycle) {}
----------------------------------------------------
1.protected void finishLoad() {}
這個函數最先執行,但是它實際上沒有什么用處(我感覺)。因為:
這個函數只在頁面池中沒有某一個頁面類、需要生成一個新的頁面對象時才調用。這里就有一個陷阱:如果你的tomcat啟動時使用了- Dorg.apache.tapestry.disable-caching=true(為了調試方便而設),那么你每次刷新頁面時,它都會執行(因為每個request都會新生成一個頁面類對象),造成了它總是執行的假象。在實際的部署時,會使用caching,則這個函數執行的機會很少。所以要注意。
初始化的代碼放在4 pageBeginRender()中
2.public void pageValidate(PageEvent event) {}
如果實現了PageValidateListener接口,則可以在這里進行驗證,比如訪問權限等。執行完1后,它就開始執行。
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {}
如果實現了IExternalPage接口,則可以從這里取得由外面傳過來的參數。執行2后,執行到這里。在這里可以把那些參數取出,賦給頁面類。
4.public void pageBeginRender(PageEvent event) {}
執行完3后,將執行本函數。但是這時從客戶端傳過來的參數還沒有被賦值(如果提交了表單的話)。這里可以進行一些初始化操作。
5.執行完4后,如果有表單提交,在這里將會取出那些值,賦給對應的字段。(注意:只是將表單中有的值賦過來)
6.public void submit()
如果有表單提交的話,在這里將進行對應的操作。因為此時各字段已經取好值了,所以可以拿來直接用。
7.protected void prepareForRender(IRequestCycle cycle) {}
最后才執行這個方法。我們可以在其中進行為了在頁面上顯示數據而進行的操作,比如取得什么對象什么的,因為這里頁面類的屬性賦值已經結束,可以直接拿來使用了。
注意:如果執行了6,則還要執行4,再執行7。如果沒有6,4完了就直接是7。
以上是我所總結的執行順序,不當之處請指出。
-----------------------------------------------------
最開始學tapestry的時候,覺得“怎么有這么多地方需要持久啊”。原來以前只知道pageBeginRender這個函數,什么初始化操作都放在它里面??墒撬窃谫x值之前執行,所以拿到的字段多都是空的,卻都以為是沒有持久化的緣故。所以在客戶端里放了一大堆的@Hidden,或者 session中持久,非常麻煩,,,對tapestry也產生的懷疑?,F在才知道那些需要取得客戶端傳來的參數的代碼,最好放在 prepareForRender里,很多不必要的持久都可以省掉了。
第一,頁面是頁面,頁面跳轉的時候,需要清空properties數據,否則,這些數據保存在session里面,很容易造成bug。打個比方說吧,initialize()這個方法,的確,在頁面表現的時候,執行兩次。頁面表現之前,初始化你的頁面,然后頁面表現你的業務邏輯,比如你要顯示什么新聞呀等等。。。最后,頁面在結束表現之前,再次執行這個方法,將你的properties還原為初始值,這樣,在你的下次再訪問該頁面的時候,不會因為 properties的值已經改變而造成意想不到的錯誤。
第二,提交一般是指表單,也就是formSubmit。如果你希望這個表單在提交之前就有初始值,也很容易,將ognl對應的get方法對應的成員變量初始化一個值就可以。比如說用initialize()來初始化。在你submit之后,ognl會自動調用properties相應的set方法賦值,你在form對應的監聽方法進行數據處理就可以了。
第三,其它的Tapestry自帶方法就不說了。什么validate()等等,都不提,只講這5個方法:
initialize()
detach()
attach()
pageBeginRender()
pageAfterRender()
它們的執行是有先后順序的,其中只有initialize()方法會執行兩次,其它的都執行一次。這些特點,足夠你利用來做很多事。
頁面在表現(render)的時候,我只以direct service舉例:
1)執行initialize(),初始化該頁面的properties,這些properties都應該是客戶端的瞬時狀態。
2)執行attach(IEngine value),獲取你的engine。所以,你可以利用這個方法往你的web容器里面加載服務。
3)執行pageBeginRender(),同樣是用來在頁面表現之前,給你希望的變量賦值。。比如說,我基本上是用這個方法來獲取Visit對象中儲存的session值。
4)頁面表現業務邏輯。你的什么Foreach啊,等等,現在才開始執行。
5)執行pageEndRender()。在你的頁面業務邏輯表現完之后,如果你希望有什么后續工作,可以在這里執行。
6)執行detach()的super(),也就是執行AbstractPage里面Tapestry自己的detach(),目的是為了清空該頁面所調用的engine,visit,requestCycle。因為如果不清空的話,比如什么用戶信息的話,就可能會泄露。這個方法的存在是 Tapestry基于安全性的考慮。
7)執行initialize(),再次將你的properties恢復為初始值。
8)執行detach()里面,你自己寫的內容。。
以上僅僅最簡單的情況下,這5種方法的執行順序。。。
注意啦,Delegate堂而皇之地作為“一等公民”在C#中“直接支持”,而Tapestry這樣的Java社區的著名項目又“轉而采用”,給個理由先? 閱讀全文
<create-instance class="org.apache.tapestry.multipart.MultipartDecoderImpl,maxSize=-1" model="threaded" />
</implementation>
<implementation service-id="tapestry.multipart.ServletMultipartDecoder">
<create-instance class="org.apache.tapestry.multipart.MultipartDecoderImpl,maxSize=-1" model="threaded" />
</implementation>
這些配置文件主要包括:service-point(服務點), implementation(服務實現),configuration-point(配置點)和contribution(配置實現)三個關鍵概念。
其中,服務點定義了服務的接口與默認實現,implementation可以覆蓋服務點的默認實現,服務點ID和配置點ID在一個模塊中必須唯一。 閱讀全文