电竞比分网-中国电竞赛事及体育赛事平台

分享

深入理解Tapestry的Rewind Tapestry...

 昵稱294 2007-01-16
深入理解Tapestry的Rewind   作者:   tapestry
關(guān)鍵字:   tapestry rewind    

Tapestry的rewind一直是學(xué)習(xí)和使用Tapestry的難點(diǎn),rewind是用來處理表單提交的,表單默認(rèn)使用的是 DirectService來提交。在詳細(xì)介紹之前,先說明下此文中需要用到的一些概念,首先是表單組件,我這里指的是指繼承自 AbstractFormComponent類的組件,例如:TextField、TextArea、Checkbox等,而不是具體的Form組件,表 單組件使用時(shí)必須在Form組件中,這些組件在rewind時(shí)調(diào)用繼承自AbstractFormComponent的 rewindFormComponent來讀取數(shù)據(jù),并將數(shù)據(jù)賦值給容器或者頁面。
我們來看一下最簡單的TextField組件,組件定義如下

代碼
  1. <input  jwcid="price@TextField" type="text" value="ognl:picture.price"  translator="translator:number,pattern=##.##"  validators="validators:min=0" displayName="價(jià)格" class="input_text"/>  

再看一下TextField中的rewindFormComponent組件方法
代碼
  1. protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) {  
  2.        //從請求中得到參數(shù)值  
  3.         String value = cycle.getParameter(getName());  
  4.   
  5.         try {  
  6.              //用translator來轉(zhuǎn)換值  
  7.             Object object = getTranslatedFieldSupport().parse(this, value);  
  8. //用validators來驗(yàn)證值  
  9.             getValidatableFieldSupport().validate(this, writer, cycle, object);  
  10.             //賦值給容器或者頁面  
  11.             setValue(object);  
  12.         } catch (ValidatorException e) {  
  13.             getForm().getDelegate().record(e);  
  14.         }  
  15.     }  

可以看到在rewindFormComponent中,主要是從請求中取得用戶輸入的值,然后進(jìn)行處理,最后賦值給容器或者頁面,上面的例子中會 調(diào)用頁面類的getPicture().setPrice(“用戶輸入的值”)來進(jìn)行賦值。這樣整個(gè)表單的提交就可以理解為所有的表單組件讀取用戶輸入的 值并賦值給頁面的過程。
整個(gè)表單提交的詳細(xì)處理過程如下:
    * initialize():頁面初始化
    * pageBeginRender() ("rewind"):getRequestCycle().isRewinding()為true
    * rewind of the form / setting of properties:所有表單組件調(diào)用rewindFormComponent來取值賦值
    * Deferred listeners (for Submit components):調(diào)用Submit組件的listener
    * Form‘s listener:調(diào)用Form組件的listener
    * pageEndRender() ("rewind"): getRequestCycle().isRewinding()為true
    * pageBeginRender() (normal): getRequestCycle().isRewinding()為false
    * pageEndRender() (normal): getRequestCycle().isRewinding()為false
我 們可以看到pageBeginRender和pageEndRender被調(diào)用了兩次,兩次中的區(qū)別為RequestCycle(). isRewinding,因?yàn)槲覀冊谑褂脮r(shí)經(jīng)常利用pageBeginRender的初始化值,所以這里有很多使用上的誤區(qū),如果在 pageBeginRender中從數(shù)據(jù)庫讀取數(shù)據(jù)來初始化跟表單提交無關(guān)的變量的話,就可能被調(diào)用兩次,這個(gè)是應(yīng)該避免的。什么叫跟表單提交無關(guān)的變量 呢,就是表單組件中跟賦值無關(guān)的,例如上邊提到的value="ognl:picture.price",這時(shí)picture就是與表單提交相關(guān)的變量, 如果你沒有初始化,那么在賦值時(shí)調(diào)用getPicture().setPrice()就會出現(xiàn)空指針異常,因?yàn)檫@是的picture為null。我們舉個(gè) 例子來看一下表單無關(guān)的變量,假如這個(gè)picture頁面會顯示一個(gè)創(chuàng)建picture的表單和所有picture的列表,那這個(gè)picture的列表就 是與表單提交無關(guān)的變量,如果你在pageBeginRender中初始化的話,就需要區(qū)分是否rewind,否則表單提交時(shí)就會被初始化兩次,讓我們看 一下代碼:
代碼
  1. public abstract void setPictures(List<Picture> pictures);  
  2. public abstract void setPictureInList();//用于For中的value  
  3. public abstract void setPicture(Picture picture);//用于表單創(chuàng)建  
  4. public abstract Picture getPicture();  
  5. public void pageBeginRender(PageEvent event) {  
  6. if(getPicture()==null){  
  7. setPicture(new Picture());  
  8. }  
  9. setPictures(getPictureService().findAll());  
  10. }  
判 斷picture是否為null并賦值在頁面顯示和rewind中都是需要的,因?yàn)轫撁骘@示時(shí),需要調(diào)用getPicture().getPrice (),頁面rewind時(shí),需要調(diào)用getPicture().setPrice(),這兩個(gè)階段中的picture都不能為null。但 setPictures會在表單提交時(shí)被調(diào)用兩次,在rewind階段初始化它是沒有用處的,所以這時(shí)就要對是否rewind進(jìn)行判斷。修改后的代碼如 下:
代碼
  1. public void pageBeginRender(PageEvent event) {  
  2. if(getPicture()==null){  
  3. setPicture(new Picture());  
  4. }  
  5. if (!event.getRequestCycle().isRewinding()) {  
  6. setPictures(getPictureService().findAll());  
  7. }  
  8. }  
這 樣就可以避免在rewind時(shí)對pictures進(jìn)行不必要的賦值。這里還要提到的一點(diǎn)是頁面顯示和提交后的頁面很可能不是同一個(gè)頁面類的實(shí)例,大家都知 道頁面類的實(shí)例是從實(shí)例池取到的,用戶打開頁面顯示表單完后的頁面類實(shí)例和用戶提交表單時(shí)的用來rewind的頁面類實(shí)例不一定是同一個(gè),即使是一個(gè)實(shí) 例,也是被重新初始化過的,不要想當(dāng)然的認(rèn)為顯示表單后再提交那個(gè)實(shí)例應(yīng)該保存原來顯示的東西,這個(gè)應(yīng)該理清楚。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多