Tapestry

          記錄學習Tapestry專用布格格。很多文章都轉載網絡。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            20 隨筆 :: 0 文章 :: 4 評論 :: 0 Trackbacks

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

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

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

          可以看到在rewindFormComponent中,主要是從請求中取得用戶輸入的值,然后進行處理,最后賦值給容器或者頁面,上面的例子中會 調用頁面類的getPicture().setPrice(“用戶輸入的值”)來進行賦值。這樣整個表單的提交就可以理解為所有的表單組件讀取用戶輸入的 值并賦值給頁面的過程。
          整個表單提交的詳細處理過程如下:
            * initialize():頁面初始化
            * pageBeginRender() ("rewind"):getRequestCycle().isRewinding()為true
            * rewind of the form / setting of properties:所有表單組件調用rewindFormComponent來取值賦值
            * Deferred listeners (for Submit components):調用Submit組件的listener
            * Form's listener:調用Form組件的listener
            * pageEndRender() ("rewind"): getRequestCycle().isRewinding()為true
            * pageBeginRender() (normal): getRequestCycle().isRewinding()為false
            * pageEndRender() (normal): getRequestCycle().isRewinding()為false
          我 們可以看到pageBeginRender和pageEndRender被調用了兩次,兩次中的區別為RequestCycle(). isRewinding,因為我們在使用時經常利用pageBeginRender的初始化值,所以這里有很多使用上的誤區,如果在 pageBeginRender中從數據庫讀取數據來初始化跟表單提交無關的變量的話,就可能被調用兩次,這個是應該避免的。什么叫跟表單提交無關的變量 呢,就是表單組件中跟賦值無關的,例如上邊提到的value="ognl:picture.price",這時picture就是與表單提交相關的變量, 如果你沒有初始化,那么在賦值時調用getPicture().setPrice()就會出現空指針異常,因為這是的picture為null。我們舉個 例子來看一下表單無關的變量,假如這個picture頁面會顯示一個創建picture的表單和所有picture的列表,那這個picture的列表就 是與表單提交無關的變量,如果你在pageBeginRender中初始化的話,就需要區分是否rewind,否則表單提交時就會被初始化兩次,讓我們看 一下代碼:
          代碼
          1. public?abstract?void?setPictures(List<Picture>?pictures);??
          2. public?abstract?void?setPictureInList();//用于For中的value??
          3. public?abstract?void?setPicture(Picture?picture);//用于表單創建??
          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中都是需要的,因為頁面顯示時,需要調用getPicture().getPrice (),頁面rewind時,需要調用getPicture().setPrice(),這兩個階段中的picture都不能為null。但 setPictures會在表單提交時被調用兩次,在rewind階段初始化它是沒有用處的,所以這時就要對是否rewind進行判斷。修改后的代碼如 下:
          代碼
          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時對pictures進行不必要的賦值。這里還要提到的一點是頁面顯示和提交后的頁面很可能不是同一個頁面類的實例,大家都知 道頁面類的實例是從實例池取到的,用戶打開頁面顯示表單完后的頁面類實例和用戶提交表單時的用來rewind的頁面類實例不一定是同一個,即使是一個實 例,也是被重新初始化過的,不要想當然的認為顯示表單后再提交那個實例應該保存原來顯示的東西,這個應該理清楚。
          posted on 2007-03-30 22:32 Tapestry 閱讀(472) 評論(0)  編輯  收藏 所屬分類: Tapestry
          主站蜘蛛池模板: 泸州市| 双牌县| 晴隆县| 平邑县| 惠州市| 沙雅县| 卢氏县| 昂仁县| 临猗县| 泰顺县| 耒阳市| 油尖旺区| 临武县| 柳州市| 肇庆市| 台江县| 辰溪县| 曲阜市| 泰安市| 辽宁省| 罗甸县| 子长县| 邹城市| 凤山市| 云安县| 甘泉县| 友谊县| 洱源县| 白山市| 延安市| 新巴尔虎左旗| 任丘市| 鹿邑县| 永德县| 冀州市| 徐水县| 邓州市| 开化县| 章丘市| 牟定县| 蕲春县|