閱讀全文
閱讀全文
對之前的該文章進行了一些修正,主要是針對finishLoad()方法。
我覺得對初學(xué)者會有一些幫助。
下面這幾個函數(shù)是我在使用的,它們的執(zhí)行順序依次從上到下。
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:調(diào)用的方法
7.protected void prepareForRender(IRequestCycle cycle) {}
----------------------------------------------------
1.protected void finishLoad() {}
這個函數(shù)最先執(zhí)行,但是它實際上沒有什么用處(我感覺)。因為:
這個函數(shù)只在頁面池中沒有某一個頁面類、需要生成一個新的頁面對象時才調(diào)用。這里就有一個陷阱:如果你的tomcat啟動時使用了- Dorg.apache.tapestry.disable-caching=true(為了調(diào)試方便而設(shè)),那么你每次刷新頁面時,它都會執(zhí)行(因為每個request都會新生成一個頁面類對象),造成了它總是執(zhí)行的假象。在實際的部署時,會使用caching,則這個函數(shù)執(zhí)行的機會很少。所以要注意。
初始化的代碼放在4 pageBeginRender()中
2.public void pageValidate(PageEvent event) {}
如果實現(xiàn)了PageValidateListener接口,則可以在這里進行驗證,比如訪問權(quán)限等。執(zhí)行完1后,它就開始執(zhí)行。
3.public void activateExternalPage(Object[] parameters, IRequestCycle cycle) {}
如果實現(xiàn)了IExternalPage接口,則可以從這里取得由外面?zhèn)鬟^來的參數(shù)。執(zhí)行2后,執(zhí)行到這里。在這里可以把那些參數(shù)取出,賦給頁面類。
4.public void pageBeginRender(PageEvent event) {}
執(zhí)行完3后,將執(zhí)行本函數(shù)。但是這時從客戶端傳過來的參數(shù)還沒有被賦值(如果提交了表單的話)。這里可以進行一些初始化操作。
5.執(zhí)行完4后,如果有表單提交,在這里將會取出那些值,賦給對應(yīng)的字段。(注意:只是將表單中有的值賦過來)
6.public void submit()
如果有表單提交的話,在這里將進行對應(yīng)的操作。因為此時各字段已經(jīng)取好值了,所以可以拿來直接用。
7.protected void prepareForRender(IRequestCycle cycle) {}
最后才執(zhí)行這個方法。我們可以在其中進行為了在頁面上顯示數(shù)據(jù)而進行的操作,比如取得什么對象什么的,因為這里頁面類的屬性賦值已經(jīng)結(jié)束,可以直接拿來使用了。
注意:如果執(zhí)行了6,則還要執(zhí)行4,再執(zhí)行7。如果沒有6,4完了就直接是7。
以上是我所總結(jié)的執(zhí)行順序,不當(dāng)之處請指出。
-----------------------------------------------------
最開始學(xué)tapestry的時候,覺得“怎么有這么多地方需要持久啊”。原來以前只知道pageBeginRender這個函數(shù),什么初始化操作都放在它里面。可是它是在賦值之前執(zhí)行,所以拿到的字段多都是空的,卻都以為是沒有持久化的緣故。所以在客戶端里放了一大堆的@Hidden,或者 session中持久,非常麻煩,,,對tapestry也產(chǎn)生的懷疑。現(xiàn)在才知道那些需要取得客戶端傳來的參數(shù)的代碼,最好放在 prepareForRender里,很多不必要的持久都可以省掉了。
第一,頁面是頁面,頁面跳轉(zhuǎn)的時候,需要清空properties數(shù)據(jù),否則,這些數(shù)據(jù)保存在session里面,很容易造成bug。打個比方說吧,initialize()這個方法,的確,在頁面表現(xiàn)的時候,執(zhí)行兩次。頁面表現(xiàn)之前,初始化你的頁面,然后頁面表現(xiàn)你的業(yè)務(wù)邏輯,比如你要顯示什么新聞呀等等。。。最后,頁面在結(jié)束表現(xiàn)之前,再次執(zhí)行這個方法,將你的properties還原為初始值,這樣,在你的下次再訪問該頁面的時候,不會因為 properties的值已經(jīng)改變而造成意想不到的錯誤。
第二,提交一般是指表單,也就是formSubmit。如果你希望這個表單在提交之前就有初始值,也很容易,將ognl對應(yīng)的get方法對應(yīng)的成員變量初始化一個值就可以。比如說用initialize()來初始化。在你submit之后,ognl會自動調(diào)用properties相應(yīng)的set方法賦值,你在form對應(yīng)的監(jiān)聽方法進行數(shù)據(jù)處理就可以了。
第三,其它的Tapestry自帶方法就不說了。什么validate()等等,都不提,只講這5個方法:
initialize()
detach()
attach()
pageBeginRender()
pageAfterRender()
它們的執(zhí)行是有先后順序的,其中只有initialize()方法會執(zhí)行兩次,其它的都執(zhí)行一次。這些特點,足夠你利用來做很多事。
頁面在表現(xiàn)(render)的時候,我只以direct service舉例:
1)執(zhí)行initialize(),初始化該頁面的properties,這些properties都應(yīng)該是客戶端的瞬時狀態(tài)。
2)執(zhí)行attach(IEngine value),獲取你的engine。所以,你可以利用這個方法往你的web容器里面加載服務(wù)。
3)執(zhí)行pageBeginRender(),同樣是用來在頁面表現(xiàn)之前,給你希望的變量賦值。。比如說,我基本上是用這個方法來獲取Visit對象中儲存的session值。
4)頁面表現(xiàn)業(yè)務(wù)邏輯。你的什么Foreach啊,等等,現(xiàn)在才開始執(zhí)行。
5)執(zhí)行pageEndRender()。在你的頁面業(yè)務(wù)邏輯表現(xiàn)完之后,如果你希望有什么后續(xù)工作,可以在這里執(zhí)行。
6)執(zhí)行detach()的super(),也就是執(zhí)行AbstractPage里面Tapestry自己的detach(),目的是為了清空該頁面所調(diào)用的engine,visit,requestCycle。因為如果不清空的話,比如什么用戶信息的話,就可能會泄露。這個方法的存在是 Tapestry基于安全性的考慮。
7)執(zhí)行initialize(),再次將你的properties恢復(fù)為初始值。
8)執(zhí)行detach()里面,你自己寫的內(nèi)容。。
以上僅僅最簡單的情況下,這5種方法的執(zhí)行順序。。。
注意啦,Delegate堂而皇之地作為“一等公民”在C#中“直接支持”,而Tapestry這樣的Java社區(qū)的著名項目又“轉(zhuǎn)而采用”,給個理由先? 閱讀全文
<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(服務(wù)點), implementation(服務(wù)實現(xiàn)),configuration-point(配置點)和contribution(配置實現(xiàn))三個關(guān)鍵概念。
其中,服務(wù)點定義了服務(wù)的接口與默認(rèn)實現(xiàn),implementation可以覆蓋服務(wù)點的默認(rèn)實現(xiàn),服務(wù)點ID和配置點ID在一個模塊中必須唯一。 閱讀全文
現(xiàn)在的框架太多了,結(jié)合使用可不是每個人都搞得來了,很少有人有那么多時間,把所有的框架測試一邊,然后結(jié)合在一起使用,Matt Raible的AppFuse給大家一個結(jié)合使用的Demo,還提供了一些開發(fā)模式,使用他提供的開發(fā)模式作一些例子非常快,可是如果讓我們做一些東西,卻不是那么簡單,我們有太多事情不知道。
以前認(rèn)真研究過AppFuse的各個部分,其中吸引人但也最亂的部分就是許多自動過程。Matt Raible確實把Ant使用的出神入化,后來我遇到不會的Ant用法,我也嘗試在AppFuse里查找可能的用法。另一個就是自動代碼生成機制,大多是用XDoclet完成,但是撰寫自己XDoclet生成模版確實不是件容易的事,當(dāng)頁面有許多特殊情況的時候,這種自動生成機制實在只能作為一個輔助手段,只可以作為起始的模版,以后我們?nèi)绻薷牧四P?,我們很難再通過這種生成機制生成頁面和類,所有的工作我們要學(xué)著自己去作,這時候生成的代碼就是一場噩夢,維護更加復(fù)雜。
當(dāng)然有一些框架可以彌補這種生成的代碼不好維護的問題,如Tapestry,另一個類似于AppFuse,號稱MDA框架的Trails也使用這個作為前臺現(xiàn)實的框架,可見Tapestry已經(jīng)在這方面有一定的改善。不過Trails還是剛剛起步,未來還很難說。
我想,在對Ant和XDoclet還并不熟練時,在沒有這種開發(fā)意識的情況下,還很難使用AppFuse來開發(fā),但是AppFuse對我們來說有很多參考價值,它可以教會我們?nèi)绾问褂肧pring,它可以教會我們?nèi)绾螌慣estCase測試,也給我們很多啟發(fā),怎樣才能盡可能的自動化代碼工作,怎樣優(yōu)化我們的工作流程。
我現(xiàn)在一直關(guān)注著Trails,在許多人看來Trails與AppFuse很類似,不知道它會發(fā)展到什么程度,它至少在表面看來比AppFuse簡單,好像要簡單一些,這是我們最需要的。
個人情感,日貨是要抵制地。
摘錄達(dá)人一句話:“Rails的出現(xiàn)只是給了人們一種新的選擇,開發(fā)者應(yīng)該學(xué)習(xí)一系列的語言,應(yīng)該懂得在合適的時候選擇合適的工具來解決問題”——Venners
斷斷續(xù)續(xù)接觸Tapestry很久了,和我接觸的其它很多技術(shù)一樣,都嚴(yán)重欠缺深度理解。雖然項目組使用Tapestry等相關(guān)技術(shù)已經(jīng)有一年多了,但是在今天我才有了些深入學(xué)習(xí)Tapestry的興趣。
TSS上的一篇文章探討JSF和Tapestry http://www.theserverside.com/articles/article.tss?l=JSFTapestry 做技術(shù)還是有段時間了,技術(shù)本就沒有什么好壞,看見這篇文章唯一希望的就是Howard能看見,然后在Tapestry后續(xù)版本中博采眾長。
雖然JSF和Tapestry都是基于組件開發(fā)的,但是選擇彼此,從某種程度講本就是觀念的選擇。
觀念不觀念不太明白,反正這個世界是不太平的。這不 Is Ajax gonna kill the web frameworks? 殺手又來了。