<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    征服jsf

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      6 隨筆 :: 0 文章 :: 27 評(píng)論 :: 0 Trackbacks

    2007年11月2日 #

    UIComponent實(shí)現(xiàn)了StateHolder接口,StateHolder接口表示組件具有了狀態(tài)。
    StateHolder接口中常用到saveState,restoreState兩個(gè)方法,在開發(fā)自定義組件的時(shí)候,需要實(shí)現(xiàn)它們,具體使用上經(jīng)常是把你的組件中全局變量進(jìn)行狀態(tài)化,就是在Object[]中定義它們,jsf在恢復(fù)和保存兩個(gè)階段分別調(diào)用組件的這兩個(gè)方法,把頁(yè)面的狀態(tài)數(shù)據(jù)恢復(fù)在Object[],把組件的Object[]數(shù)據(jù)渲染到頁(yè)面。isTransient,setTransient方法表式,你的組件是否想狀態(tài)化。

    UIComponent組件主要api
    1.public abstract java.util.Map getAttributes()  該方法會(huì)獲得該組件的所有屬性值

    2. public abstract javax.faces.el.ValueBinding getValueBinding(java.lang.String name) 該方法會(huì)從組件的值綁定集合表中獲取對(duì)應(yīng)的值綁定對(duì)象,值綁定對(duì)象(ValueBinding )的目的是使用EL表達(dá)式解析你綁定的模型值,例如頁(yè)面有個(gè)(#use.name),那么值綁定就會(huì)解析這個(gè)字符串,通過變量解析獲取User對(duì)象,再用值解析獲取name值。

    3.public abstract java.lang.String getClientId(javax.faces.context.FacesContext context) 主要是在UIViewRoot組件中生成組件在頁(yè)面的映射Id,如果你為組件定義了一個(gè)id,那么他會(huì)基于這個(gè)id生成一個(gè)具有組件層次的客戶端Id,使用':'來(lái)分隔,如果沒有為組件定義id,那么會(huì)動(dòng)態(tài)生成一個(gè)id,例如會(huì)在頁(yè)面渲染結(jié)果看到'form1:input1'這樣的Id,就是告訴你一個(gè)Input組件的id是'input',它在id是'form1'的form組件中。clientId常常在jsf內(nèi)部對(duì)組件用來(lái)整理,定位。

     4.public abstract java.lang.String getFamily() 告訴你這個(gè)組件屬于那個(gè)家族的,用的不多。主要是內(nèi)部創(chuàng)建渲染類使用。

    5. public abstract java.lang.String getId() 這個(gè)Id就是頁(yè)面上你指定的組件Id,它可以讓你方便的查找組件樹上的組件,最好給你的頁(yè)面組件都設(shè)定一個(gè)id,在服務(wù)端開發(fā)有時(shí)候會(huì)用到,如果沒有設(shè)定,jsf會(huì)自動(dòng)生成一個(gè)唯一的id,如果自定義id在組件中有沖突,那么jsf會(huì)拋出id沖突異常。

    6.public abstract javax.faces.component.UIComponent getParent() 得到該組件的父組件,注意:html標(biāo)記不會(huì)成為一個(gè)組件。

    7. public abstract boolean isRendered() 如果該組件這個(gè)方法設(shè)定為false,那么該組件以及它的子組件都會(huì)停止解碼,驗(yàn)證,值更新,渲染等操作

    8. public abstract java.lang.String getRendererType()  指定了該組件使用哪個(gè)渲染類進(jìn)行渲染,這就是組件與渲染分離,并且互相可以復(fù)用的機(jī)制。

    9. public abstract boolean getRendersChildren();  如果組件的此方法設(shè)定為真,那么jsf將繼續(xù)尋找它的子組件進(jìn)行渲染。否者渲染只渲染到當(dāng)前組件。

    10. public abstract java.util.List getChildren(); 獲得該組件的直屬子組件列表

    11. public abstract int getChildCount() 獲得獲得該組件的直屬子組件列表數(shù)

    12.public abstract javax.faces.component.UIComponent findComponent(java.lang.String expr) 尋找該組件的子組件,通過頁(yè)面上指定的組件Id,在它的父組件的findComponent去查找這個(gè)組件,一般用于自定義組件開發(fā)上,例如:jsf消息渲染的時(shí)候就是通過findComponent方法去尋找for屬性定義的組件。

    13.public abstract java.util.Map getFacets() 得到該組件的所有facet類型的組件,facet組件主要作用:一個(gè)功能強(qiáng)大的組件中會(huì)有很多增強(qiáng)功能,這些增強(qiáng)功能可以定義成多個(gè)小的facet組件,這樣可以從組件的主功能中分解開,降低組件內(nèi)部功能的耦合性,同時(shí)也可以做為組件的插件機(jī)制來(lái)擴(kuò)展。

    14.public abstract java.util.Iterator getFacetsAndChildren() 獲取自己所以的直屬子組件和facet組件,常用在子組件查找操作上,例如jsf核心機(jī)制中,遍歷組件增加事件時(shí)就要遞歸使用此方法。

    15.    public abstract void broadcast(javax.faces.event.FacesEvent event) 對(duì)于jsf生命周期的幾個(gè)階段都會(huì)用到遞歸遍歷組件的事件,使用的就是這個(gè)方法,常用在內(nèi)部機(jī)制上。標(biāo)準(zhǔn)的觀察者模式。

    16.    public abstract void decode(javax.faces.context.FacesContext context) jsf聲明周期中的解碼部分就是調(diào)用此方法,主要用在應(yīng)用請(qǐng)求值階段,通過遞歸遍歷,每一個(gè)組件會(huì)在這個(gè)階段操作request等容器對(duì)象來(lái)實(shí)現(xiàn)并隱藏request請(qǐng)求的表現(xiàn)邏輯,并封裝成事件交給組件的事件列表,由后面的階段來(lái)處理。需要注意的是很可能此方法會(huì)把工作委托給渲染類的decode上,所以jsf的渲染機(jī)制不僅僅是簡(jiǎn)單的輸出html等展現(xiàn)標(biāo)記,還用來(lái)封裝和隱藏容器內(nèi)的通信機(jī)制,讓容器內(nèi)對(duì)象從我們眼前消失!

    17. 

        public abstract void encodeBegin(javax.faces.context.FacesContext context)
                throws java.io.IOException;

        public abstract void encodeChildren(javax.faces.context.FacesContext context)
                throws java.io.IOException;

        public abstract void encodeEnd(javax.faces.context.FacesContext context)
                throws java.io.IOException;

    組件渲染階段需要經(jīng)歷的步驟,渲染機(jī)制是一個(gè)復(fù)雜的過程,原理上是把tag標(biāo)記渲染的工作委托給了servlet之上來(lái)處理,jsf 的tag標(biāo)記只作為組件,視圖之間的映射之用。這三個(gè)階段更明確了渲染成視圖標(biāo)記這樣一個(gè)工作,同樣可以委托給渲染類去做。

     18.protected abstract void addFacesListener(javax.faces.event.FacesListener listener) 為組件增加監(jiān)聽,標(biāo)準(zhǔn)的觀察者模式。

    19.protected abstract javax.faces.event.FacesListener[] getFacesListeners(java.lang.Class clazz) 得到組件的監(jiān)聽列表,監(jiān)聽器在組件的事件列表遍歷時(shí)會(huì)被調(diào)用,clazz參數(shù)是用來(lái)區(qū)分不同的監(jiān)聽器,目前常用ActionListener.class,ValueChangeListener.class

    20.protected abstract void removeFacesListener(javax.faces.event.FacesListener listener);從組件的監(jiān)聽列表中刪除不需要的監(jiān)聽器。

    21.public abstract void queueEvent(javax.faces.event.FacesEvent event) 把新創(chuàng)建的事件增加到組件的事件隊(duì)列,此方法常常用在應(yīng)用請(qǐng)求值階段,每個(gè)組件會(huì)根據(jù)條件創(chuàng)建自己的事件,加入到事件列表,所有事件會(huì)全局的放入U(xiǎn)IViewRoot組件中,UIViewRoot組件是jsf各個(gè)階段對(duì)組件樹進(jìn)行遞歸遍歷處理的啟動(dòng)點(diǎn)。

    22.

       public abstract void processRestoreState(javax.faces.context.FacesContext context,
                                                 java.lang.Object state);

        public abstract void processDecodes(javax.faces.context.FacesContext context);

        public abstract void processValidators(javax.faces.context.FacesContext context);

        public abstract void processUpdates(javax.faces.context.FacesContext context);

        public abstract java.lang.Object processSaveState(javax.faces.context.FacesContext context);

        jsf生命周期中組件需要處理的五個(gè)重要階段:恢復(fù)狀態(tài),解碼,驗(yàn)證,更新,保持狀態(tài)(另外包括調(diào)用應(yīng)用,渲染),開發(fā)自定義組件,需要特別關(guān)注這些方面,渲染階段由組件的編碼方法實(shí)現(xiàn),調(diào)用應(yīng)用階段則是actionListener監(jiān)聽器集合的處理期。

    23. protected abstract javax.faces.context.FacesContext getFacesContext() 獲取jsf上下文環(huán)境,F(xiàn)acesContext 是一個(gè)線程安全模型,在設(shè)計(jì)上接近pojo,所以在jsf環(huán)境對(duì)FacesContext的調(diào)用得到了簡(jiǎn)化,但是jsf整體的編程規(guī)則上更希望你能把FacesContext 作為命令參數(shù)傳遞給各個(gè)實(shí)現(xiàn)細(xì)節(jié),以保證上下文的真實(shí)性,這一點(diǎn)在開發(fā)自定義組件上要注意!
    24. protected abstract javax.faces.render.Renderer getRenderer(javax.faces.context.FacesContext context) 獲取當(dāng)前組件的渲染類。
    posted @ 2007-11-02 16:38 方順 閱讀(3012) | 評(píng)論 (0)編輯 收藏

    2007年10月21日 #

       1.不要盲目使用jsf1.2規(guī)范的實(shí)現(xiàn)框架:
            目前sun,myfaces都推出了jsf1.2規(guī)范的實(shí)現(xiàn),但是各種jsf1.2支持并沒有跟上,所以小心使用。
           jsf1.2的優(yōu)勢(shì)主要體現(xiàn)在統(tǒng)一的EL表達(dá)式,也就是說(shuō)你可以在頁(yè)面上,混合使用只要支持了統(tǒng)一表達(dá)式的各種tag標(biāo)記,同時(shí)可以享受jsf在表現(xiàn)層開發(fā)上帶來(lái)的強(qiáng)大支持,這就又需要兩個(gè)規(guī)范的支持,一個(gè)是jsp規(guī)范,一個(gè)是jstl規(guī)范,jsp2.1規(guī)范支持統(tǒng)一EL,它在tomat6.0.14以后才開始支持,glassFish默認(rèn)支持,這些都是基礎(chǔ)設(shè)施,jstl把不同的taglibs定義了一個(gè)規(guī)范,你可以選擇各種實(shí)現(xiàn)了jstl規(guī)范的taglibs框架,目前大多數(shù)使用的是apache 帶的標(biāo)準(zhǔn)實(shí)現(xiàn),但是apache仍然沒有推出jstl1.2規(guī)范的實(shí)現(xiàn),只有jstl1.2規(guī)范以后開始支持統(tǒng)一EL,目前可能只有g(shù)lassfish有jstl1.2的默認(rèn)實(shí)現(xiàn),我沒有試過能不能復(fù)用在其他容器下,但是在沒有驗(yàn)證之前,請(qǐng)斟酌使用,jsf1.2在統(tǒng)一EL方面的常用應(yīng)用就是和jstl標(biāo)記混合。如果你的項(xiàng)目仍然是tomcat5.5或者jboss的容器,使用jsf1.2沒有多大優(yōu)勢(shì)!而且jsf1.2雖然推出了不同的實(shí)現(xiàn)框架,但是增強(qiáng)框架仍然沒有看到,myfaces基于jsf1.2的 Tomahawk 還沒有推出支持1.2規(guī)范的實(shí)現(xiàn),如果僅僅使用sun的標(biāo)準(zhǔn)實(shí)現(xiàn)和myfaces的標(biāo)準(zhǔn)實(shí)現(xiàn),在項(xiàng)目中你會(huì)步履維艱!

    2.如果沒有商業(yè)jsf框架選擇,請(qǐng)選擇myfaces的增強(qiáng)框架Tomahawk
      sun的標(biāo)準(zhǔn)實(shí)現(xiàn)和myfaces的標(biāo)準(zhǔn)實(shí)現(xiàn)都是針對(duì)規(guī)范該有的內(nèi)容進(jìn)行實(shí)現(xiàn),并沒有在組件方面進(jìn)行必要的增強(qiáng),這也是我主要使用Tomahawk這種對(duì)組件增強(qiáng)框架的原因。

    3.現(xiàn)階段不要相信IDE工具支持
       netbeans的可視化操作使用的是自己的jsf實(shí)現(xiàn),沒有myfaces框架的支持,需要等到6.0推出才能驗(yàn)證它的優(yōu)勢(shì),其他包括商業(yè)工具,使用后錯(cuò)誤很多,感覺就是在測(cè)試我們的接受能力,現(xiàn)階段我對(duì)jsf的可視化工具不抱希望,如果你有信心,可以試試工具!現(xiàn)階段我推薦的方式是jsf手動(dòng)開發(fā),在開發(fā)中積累經(jīng)驗(yàn)!

    4.不要隨意使用ajax支持的jsf組件。
      如果你是web2.0的支持者,現(xiàn)階段還是不要用jsf好,jsf是下一代web2.0的主導(dǎo)。如果你是標(biāo)準(zhǔn)的企業(yè)開發(fā),建議使用標(biāo)準(zhǔn)方式進(jìn)行頁(yè)面請(qǐng)求。jsf最大的貢獻(xiàn)不是支持ajax,而是內(nèi)部實(shí)現(xiàn)了一個(gè)可以透明化http無(wú)狀態(tài)的機(jī)制,這種機(jī)制讓我們?cè)陂_發(fā)上高度關(guān)注組件化業(yè)務(wù),讓我們的開發(fā)能走的更遠(yuǎn),而使用ajax在理論上和標(biāo)準(zhǔn)方式一樣,在服務(wù)端具有統(tǒng)一的模型處理,但是javascript在工程開發(fā)上是高度的復(fù)雜和麻煩,jsf在處理純html上在現(xiàn)階段也是常常出現(xiàn)一些讓人接受不了的問題,有時(shí)候需要自己手動(dòng)Hack,但是好在html還不復(fù)雜,如果頁(yè)面端大量javascript,你怎么辦,這還不算請(qǐng)求帶來(lái)的問題,ajax框架本身的質(zhì)量!

    6.如果項(xiàng)目中決定使用jsf,請(qǐng)找一個(gè)能拿的住jsf的人,整個(gè)開發(fā)不僅僅會(huì)使用jsf,還有混合使用其他頁(yè)面技術(shù),如果這個(gè)人對(duì)表現(xiàn)層的理解包括jsf的理解不夠,項(xiàng)目在很多方面的質(zhì)量會(huì)有折扣,但是對(duì)于整個(gè)開發(fā)團(tuán)隊(duì)使用jsf會(huì)比使用其他表現(xiàn)層技術(shù)更簡(jiǎn)單,更高效,開發(fā)質(zhì)量也會(huì)更高,這都要看jsf負(fù)責(zé)人的技術(shù)應(yīng)變能力了!

    5.還是老調(diào)重提,在項(xiàng)目中最好加入seam的支持,會(huì)讓jsf的開發(fā)變的簡(jiǎn)單!
    posted @ 2007-10-21 11:38 方順 閱讀(2025) | 評(píng)論 (7)編輯 收藏

    2007年10月20日 #

         前一段時(shí)間我寫過一篇共享我在項(xiàng)目中使用jsf的一些經(jīng)驗(yàn),主要是概要的提出了一些jsf使用上的建議,這次我想在文章里主要是把seam在jsf中的使用經(jīng)驗(yàn)提一下,能讓更多的人了解seam的實(shí)際應(yīng)用和優(yōu)勢(shì)。
        1.seam配置時(shí)要注意的地方:
        (1)faces-config.xml里面要加入一個(gè)seam的階段監(jiān)聽:
        
    <lifecycle>
    <phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener>
    <!-- <phase-listener>com.future.egov.jsf.ext.event.DebugPhaseListener</phase-listener> -->
    </lifecycle>

         seam動(dòng)起來(lái)的條件就是從這里發(fā)起的,seam通過這個(gè)監(jiān)聽器對(duì)jsf的各個(gè)階段進(jìn)行必要的增強(qiáng)以及植入自己的CONVERSATION生命周期,對(duì)于這個(gè)監(jiān)聽器的具體細(xì)節(jié)工作,我還需要更多時(shí)間研究,仍在了解中!
          (2) 一定要在工程類路徑的根下放置一個(gè)seam.properties文件,你可以設(shè)置為空內(nèi)容,主要是引導(dǎo)seam在初始化的時(shí)候加載這個(gè)路徑下所有標(biāo)注為seam組件的對(duì)象(通過@Name注釋),http://www.ibm.com/developerworks/cn/java/j-seam1/  seam無(wú)縫集成jsf給我了提示!
          (3)web.xml下最小配置是加入seam監(jiān)聽器
            
        <listener>
              
    <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
        
    </listener>
           在容器加載工程的時(shí)候,初始化seam框架。
          以上三處的配置,你就可以在任何容器中使用seam了!更多的配置大家可以找參考了解吧,我目前在項(xiàng)目中就使用了以上配置。其他配置主要是在seam對(duì)ajax,ejb3的支持上,不過seam很新,什么事都會(huì)發(fā)生!
       2.常用的注釋:(所有被seam定義的領(lǐng)域?qū)ο蠖伎梢哉J(rèn)為是seam組件)
         (1)@Name(XXX),需要在你的領(lǐng)域類上定義,定義了seam組件的名稱,對(duì)于jsf來(lái)說(shuō)就是backing-bean,也就是說(shuō)你不用在faces-config中配置managedbean了!

          (2)@Scope(ScopeType.XXX),可以在你的領(lǐng)域類上定義,表示這個(gè)被定義的seam組件在什么上下文中,jsf中主要包括page,event,session,application,conversation這些Scope。我在項(xiàng)目中主要使用event,session,conversation。event就是把組件放入了request中,session同理,conversation是seam獨(dú)創(chuàng)的聲命周期,conversation短聲命周期類似request,但是會(huì)保存一些jsf容易在請(qǐng)求中丟失的數(shù)據(jù)(jsf只是保存組件,不保存組件渲染的數(shù)據(jù),除非是EditableValueHolder組件,有時(shí)候需要通過myfaces的save組件和updateActionListener組件來(lái)恢復(fù)這些數(shù)據(jù)),具體保存細(xì)節(jié),需要看使用的情況,我有這樣一個(gè)經(jīng)驗(yàn):當(dāng)定義成event上下文,在頁(yè)面的一次請(qǐng)求中,有些數(shù)據(jù)請(qǐng)求時(shí)還在,但是到渲染時(shí)就不見了,常見在dataTable組件,myfaces的commandNavigation組件,但是換成conversation上下文,這些數(shù)據(jù)在渲染時(shí)又找回來(lái)了。但是對(duì)于跨度比較大層面,我還是推薦使用myfaces提供的保持機(jī)制,我一般使用updateActionListener,而save組件在seam1.2.1的環(huán)境下會(huì)出錯(cuò)。如果再有更大跨度,就可以使用conversation上下文的長(zhǎng)會(huì)話了。

           (3)@Begin(join=true),@End(beforeRedirect=true),當(dāng)觸發(fā)了帶有@Begin標(biāo)記的方法,conversation的長(zhǎng)會(huì)話就這樣開始了,主要是為了長(zhǎng)時(shí)間使用已經(jīng)加載到conversation域中的對(duì)象或者屬性(如果定義了conversation但并沒有加載的可不算):join=true就是告訴你會(huì)話中有同名值時(shí)繼續(xù)賦值,還有一個(gè)注釋參數(shù)ifOutcome=XXX,就是看你的方法返回的字符串是否和ifOutcome定義的字符串相匹配,如果匹配就開始長(zhǎng)會(huì)話。當(dāng)在長(zhǎng)會(huì)話期間執(zhí)行到某個(gè)方法帶有@End標(biāo)記那么這個(gè)長(zhǎng)會(huì)話就會(huì)結(jié)束,這樣防止了內(nèi)存泄漏問題,我認(rèn)為這是一個(gè)權(quán)衡的結(jié)果,也許用戶真的會(huì)點(diǎn)擊那個(gè)帶有結(jié)束標(biāo)記方法的按鈕。beforeRedirect為真就會(huì)在結(jié)束時(shí)清掉conversation上下文所有的信息,如果beforeRedirect=false,conversation只是變成短會(huì)話,在結(jié)束后的那次請(qǐng)求中還可以使用conversation中的數(shù)據(jù),一般會(huì)用在messages提示這個(gè)應(yīng)用場(chǎng)景中使用,但是如果要返回?cái)?shù)據(jù)列表有時(shí)就需要清空所有數(shù)據(jù),防止數(shù)據(jù)列表還會(huì)重現(xiàn)長(zhǎng)會(huì)話開始前的情況。

           (4)In(value=XXX,rquest=false,ScopeType=XXX),Out(value=XXX,rquest=false,ScopeType=XXX) seam把它定義為雙射。In是最常用的標(biāo)注,你可以使用In導(dǎo)入一個(gè)jsf的EL變量來(lái)獲取jsf模型,例如我要獲取spring的業(yè)務(wù)bean,而且業(yè)務(wù)bean已經(jīng)定義成backing bean,利用spring與jsf集成的方法:
           
        <!-- Managed Beans for options.jsp -->
        
    <application>
            
    <variable-resolver>
                org.springframework.web.jsf.DelegatingVariableResolver
            
    </variable-resolver>
            
    <locale-config>
                
    <default-locale>gbk</default-locale>
            
    </locale-config>
            
    <message-bundle>resources/MessageBundle</message-bundle>
            
    <!--  <view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler
            </view-handler>        
    -->
        
    </application>

         在seam組件中這樣聲明:
    @In(value="#{userService}", request=false)
    private UserService userService;

     這個(gè)示例為seam組件注入了由spring管理的用戶服務(wù)對(duì)象,它的value是從jsf EL變量中獲取,request=false在告訴seam,如果當(dāng)前的值沒有找到,那么設(shè)置為空,否者當(dāng)出現(xiàn)沒有找到的情況,seam會(huì)拋出空異常。
    @Out屬性主要是把處理過的屬性值會(huì)由seam重新再付給上下文也就是Out中所定義的ScopeType上下文,我認(rèn)為雖然是seam的一個(gè)特點(diǎn),但是在我的應(yīng)用中不多,主要是注入而非雙射!如果它真的能在短期Conversation中有所作用來(lái)代替Myfaces的數(shù)據(jù)保持機(jī)制,我想會(huì)好些,我目前只是在長(zhǎng)Conversation有所應(yīng)用。

    3 .@Factory,@DataModelSelection,@DataModel,它們主要來(lái)代替數(shù)據(jù)列表的使用,主要是減少了代碼量,F(xiàn)actory是在請(qǐng)求值階段就對(duì)需要實(shí)例化的對(duì)象進(jìn)行創(chuàng)建,DataModelSelection定義的屬性,可以透明的抓取數(shù)據(jù)列表選擇的單行數(shù)據(jù),DataModel屬性減少了不必要的get,set。然而我在實(shí)際的使用中由于很多不定的情況,大部分的使用上又回到j(luò)sf標(biāo)準(zhǔn)的get方式。 這種開發(fā)方式我認(rèn)為seam的目的是想屏蔽與頁(yè)面不必要的關(guān)系細(xì)節(jié),讓開發(fā)只需要重視真正的業(yè)務(wù),是一個(gè)標(biāo)準(zhǔn)的面向?qū)ο笫浇Y(jié)構(gòu),當(dāng)jsf的體系結(jié)構(gòu)的不斷優(yōu)化,類似這種開發(fā)方式我想會(huì)越來(lái)越有用。
    4. @RequestParameter是個(gè)很有用的注釋,它自動(dòng)把當(dāng)前屬性和頁(yè)面同名的request提交值綁定在一起,雖然這樣使用違背了jsf所追求的面向?qū)ο蠡?,http透明化,但是實(shí)際開發(fā)中會(huì)后很多意想不到的情況,有時(shí)候在集成式頁(yè)面這樣的做法會(huì)很有用,當(dāng)你的頁(yè)面中不僅僅有jsf標(biāo)簽就清楚了!

    seam的其他方面問題我會(huì)抽空整理一下,seam目前也是在不斷更新當(dāng)中,明年出臺(tái)的webBeans規(guī)范的前身就是seam,其實(shí)我更關(guān)注的是seam在整個(gè)j2ee體系中的角色,它到底是想替代struts的application?還是想替代spring的manager?也許有更多的想法!
    posted @ 2007-10-20 13:55 方順 閱讀(2747) | 評(píng)論 (4)編輯 收藏

    2007年9月21日 #

            ‘jsf的dataTable組件自定義控制指定行樣式的方法’  這篇文章我主要通過覆寫DataModel對(duì)象的getRowData()方法來(lái)控制DataTable每一行的行為,其實(shí)還有個(gè)標(biāo)準(zhǔn)的方式,也更加優(yōu)雅,那就是使用DataModelListener,典型的監(jiān)聽事件,jsf內(nèi)置了數(shù)據(jù)模型監(jiān)聽機(jī)制以便開發(fā)者對(duì)于數(shù)據(jù)模型每一行的控制,而且這種監(jiān)聽可以無(wú)限增加,使得對(duì)每一行控制的方式變成一個(gè)個(gè)監(jiān)聽對(duì)象,非常好用,下面就是更改過得樣例:
         
    package net.blogjava.fangshun.book;

    import java.util.List;

    import javax.faces.context.FacesContext;
    import javax.faces.el.VariableResolver;
    import javax.faces.model.DataModelEvent;
    import javax.faces.model.DataModelListener;
    import javax.faces.model.ListDataModel;

    import org.apache.myfaces.component.html.ext.HtmlDataTable;

    /**
     * 集成了ListDataModel為Book模型提供自定義樣式的支持
     * 
    @author shun.fang
     *
     
    */

    public class BookListDataModel extends ListDataModel {
        
        
    public BookListDataModel(List<Book> books) {
            
    super(books);
            
    super.addDataModelListener(new BookListDataModelListener());
        }

        
        
    /**
         * 覆寫了DataModel對(duì)象的getRowData方法,每次uiData組件從模型列表獲取新一行記錄
         * 的時(shí)候,是從這里發(fā)起的,所以在這里可以通過獲取uiData組件,來(lái)對(duì)uiData組件的狀態(tài)進(jìn)行
         * 調(diào)整。目前的調(diào)整就是根據(jù)業(yè)務(wù)的需要對(duì)uiData組件的每一行樣式進(jìn)行特殊指定。
         
    */

    //    @Override
    //    public Object getRowData() {
    //        // TODO Auto-generated method stub
    //        
    //        /////////////////////////////////////////////////////////////
    //        //通過變量解析獲取request scope中的BookList列表模型
    //        FacesContext facesContext = FacesContext.getCurrentInstance();
    //        VariableResolver vr = facesContext.getApplication().getVariableResolver();
    //        BookList bookList = (BookList)vr.resolveVariable(facesContext, "booking");    
    //        /////////////////////////////////////////////////////////////
    //        
    //        //間接得到綁定BookList列表模型的uiData組件,并向下轉(zhuǎn)型成HtmlDataTable(myfaces擴(kuò)展類型)組件
    //        HtmlDataTable table = (HtmlDataTable)bookList.getUiData();
    //        
    //        //獲取當(dāng)前行的Book實(shí)例
    //        Book book = (Book)super.getRowData();
    //        
    //        //根據(jù)當(dāng)前行Book實(shí)例的業(yè)務(wù)特征為HtmlDataTable組件設(shè)置渲染行樣式
    //        setCurrentRowStyle(table, book.getType());
    //        
    //        return book;
    //    }
        
        
    /**
         * 根據(jù)不同的類型,設(shè)置當(dāng)前行的樣式
         * 
    @param table
         * 
    @param type
         
    */

        
    private void setCurrentRowStyle(HtmlDataTable table, int type) {
            
    switch (type) {
                
    case Book.COMPUTER_BOOK:
                    
    //System.out.println("computers");
                    table.setRowStyleClass("computers");    //設(shè)置計(jì)算機(jī)書籍樣式
                    break;
                
    case Book.ART_BOOK:
                    
    //System.out.println("arts");
                    table.setRowStyleClass("arts");        //設(shè)置文學(xué)書籍樣式
                    break;
                
    case Book.ECONOMY_BOOK:
                    
    //System.out.println("C");
                    table.setRowStyleClass("economy");        //設(shè)置經(jīng)濟(jì)書籍樣式
                    break;
                
    default:
                    
    break;
            }

        }

        
        
    class BookListDataModelListener implements DataModelListener {

            
    public void rowSelected(DataModelEvent event) {
                
    // TODO Auto-generated method stub
                
                
    /////////////////////////////////////////////////////////////
                
    //通過變量解析獲取request scope中的BookList列表模型
                FacesContext facesContext = FacesContext.getCurrentInstance();
                VariableResolver vr 
    = facesContext.getApplication().getVariableResolver();
                BookList bookList 
    = (BookList)vr.resolveVariable(facesContext, "booking");    
                
    /////////////////////////////////////////////////////////////
                
                
    //間接得到綁定BookList列表模型的uiData組件,并向下轉(zhuǎn)型成HtmlDataTable(myfaces擴(kuò)展類型)組件
                HtmlDataTable table = (HtmlDataTable)bookList.getUiData();
                
                
    //獲取當(dāng)前行的Book實(shí)例
                Book book = (Book)event.getRowData();
                
    if(book != null{
                    
    //根據(jù)當(dāng)前行Book實(shí)例的業(yè)務(wù)特征為HtmlDataTable組件設(shè)置渲染行樣式
                    setCurrentRowStyle(table, book.getType());
                }

            }

            
        }

    }

     我把監(jiān)聽器BookListDataModelListener作為我的自定義模型的一個(gè)內(nèi)部類來(lái)增強(qiáng)業(yè)務(wù)聚合性,大家在使用的時(shí)候可以直接使用一些標(biāo)準(zhǔn)的DataModel,例如ListDataModel等,可以為每個(gè)監(jiān)聽器新建一個(gè)對(duì)象,然后在jsf業(yè)務(wù)層去實(shí)例化調(diào)用,不一定要向樣例那樣放在一起。但是一定要記住,event.getRowData()可能有空值(最后一行的終結(jié)處),所以要向樣例那樣,進(jìn)行非空判斷!

     

    posted @ 2007-09-21 16:28 方順 閱讀(1925) | 評(píng)論 (2)編輯 收藏

    2007年9月14日 #

         摘要:      HtmlDataTable組件屬于UIData家族的HTML數(shù)據(jù)列表實(shí)現(xiàn),組件中提供了rowStyleClass等方法來(lái)控制行的顯示,,如果你在rowStyleClass中加入兩個(gè)樣式類,并使用逗號(hào)分開,那么渲染的每一行會(huì)交替使用這兩個(gè)樣式類進(jìn)行顯示,同理多個(gè)樣式類也會(huì)循環(huán)交替顯示。但是如果我想根據(jù)業(yè)務(wù)的情況具體指定某行顯示成特定的樣式,...  閱讀全文
    posted @ 2007-09-14 15:48 方順 閱讀(3637) | 評(píng)論 (2)編輯 收藏

    2007年9月9日 #

    我目前的項(xiàng)目前端使用的是jsf+seam的架構(gòu),目前項(xiàng)目已經(jīng)進(jìn)入尾聲,我想把一些心得體會(huì)給大家說(shuō)說(shuō),以便大家在使用jsf的時(shí)候,少走彎路。

    1.異常處理問題:請(qǐng)為jsf加入seam框架,看看Seam - 無(wú)縫集成JSF,共三部分,里面告訴了你怎么在servlet容器下配合spring使用seam,seam不是一定要在ejb3和jboss下才可以使用。因?yàn)閱为?dú)使用jsf的話她的異常處理功能很簡(jiǎn)陋,跟蹤不到你想看的地方,對(duì)于開發(fā)很不方便,你只有打開日志才能看到問題所在,而seam在加入phase-listener以后,對(duì)jsf不同的生命周期都進(jìn)行了功能增強(qiáng),即使不使用seam任何的功能,她也能毫無(wú)保留的輸出所有的異常棧。

    2.css問題:如果你想在你的項(xiàng)目中使用jsf,css太重要了,很多剛開始使用jsf的人都不是很習(xí)慣jsf基于塊結(jié)構(gòu)開發(fā)頁(yè)面,因?yàn)閖sf讓你注意的是展現(xiàn)的內(nèi)容,而不是展現(xiàn)的樣式,這是完全符合w3開發(fā)html的初衷,大家使用<table><tr><td>來(lái)做頁(yè)面展現(xiàn)布局,其實(shí)是錯(cuò)誤已久的方法,如果在jsf中能了解如何使用css進(jìn)行布局,jsf不適合復(fù)雜頁(yè)面設(shè)計(jì)這句話就不攻自破了。

    3.細(xì)心的使用dataTable組件,數(shù)據(jù)列表是最常用的頁(yè)面組件,但是我毫不留情的說(shuō)jsf的dataTable組件的實(shí)現(xiàn)簡(jiǎn)直太濫了,它就是jsf開發(fā)一大禍根。沒有很方便的解決特定行樣式顯示的問題,沒有解決回退按鈕風(fēng)險(xiǎn)問題,沒有dataScroll和dataTable組件進(jìn)行數(shù)據(jù)庫(kù)分頁(yè)的優(yōu)雅辦法,數(shù)據(jù)提交的幻影問題,我的開發(fā)很多時(shí)間用在了dataTable的和其他組件塊融合上面。不過jsf1.2通過統(tǒng)一el,加入了對(duì)jstl的foreach標(biāo)記的支持,我雖然還沒有使用,但是我認(rèn)為這有可能成為數(shù)據(jù)列表開發(fā)的一個(gè)有力補(bǔ)充。

    4.建議把jsf的模型bean和后臺(tái)的業(yè)務(wù)bean合二為一,這樣可以在前端提交頁(yè)面與模型綁定的同時(shí),完成業(yè)務(wù)bean的數(shù)據(jù)封裝,并且交由服務(wù)層處理一氣呵成。這樣做有個(gè)好處,就是我們會(huì)想方設(shè)法通過各種手段在第一時(shí)間就完成模型bean對(duì)業(yè)務(wù)bean的封裝,消除服務(wù)層對(duì)dto的依賴。這樣是可行的,因?yàn)閖sf的頁(yè)面綁定機(jī)制提供了很好的幫助。

    5.請(qǐng)考慮多的使用convert組件,比如列表頁(yè)面有個(gè)radio塊,提交radio值就是一個(gè)int數(shù)值,然后在展現(xiàn)邏輯去恢復(fù)這個(gè)radio值對(duì)應(yīng)的業(yè)務(wù)模型,這樣增加了展現(xiàn)邏輯處理頁(yè)面數(shù)據(jù)的負(fù)擔(dān),而且不好管理,如果把這個(gè)工作放在自定義的convert中,讓convert在頁(yè)面上顯示int數(shù)值,在提交上尋找對(duì)象,那么頁(yè)面和服務(wù)層就屏蔽了這樣的工作,看到的都是對(duì)象的進(jìn)出。

    6.我使用了myfaces一個(gè)自己的組件<t:updateListener>,就是跨頁(yè)面專遞參數(shù),非常好用,剛使用jsf的朋友,可以看到跳轉(zhuǎn)的下一個(gè)頁(yè)面用它怎么做,但是建議傳遞模型對(duì)象,不要傳遞數(shù)值,你使用jsf就是因?yàn)樗腔趯?duì)象考慮頁(yè)面設(shè)計(jì)的。

    7.小心使用session來(lái)處理jsf,jsf過多的使用了session,但是我可以肯定一點(diǎn),展現(xiàn)層一定是需要基于狀態(tài)的方式來(lái)做的,這樣可以簡(jiǎn)化開發(fā),無(wú)狀態(tài)的方式會(huì)帶來(lái)更多的無(wú)序代碼。不是每個(gè)人都是高手??梢钥紤]使用seam的conversation來(lái)處理,她的長(zhǎng)會(huì)話特別適合業(yè)務(wù)編輯,默認(rèn)的短會(huì)話會(huì)填補(bǔ)jsf有時(shí)容易丟失的短期數(shù)據(jù)。

    8.調(diào)試jsf的問題:有時(shí)你使用jsf想知道你的數(shù)據(jù)在哪個(gè)階段變化了,你不會(huì)把jsf代碼加入到自己的工程中來(lái)調(diào)試把,請(qǐng)加入自定義的phaseListener,繼承phaseListener這個(gè)接口,你可以在把你的程序設(shè)置在任何階段跳出來(lái)進(jìn)行調(diào)試。

    9.分頁(yè)的問題:在google搜一下,有個(gè)http://www.tkk7.com/steady/archive/2005/12/30/26013.aspx提供了分頁(yè)的方式,我就在使用,這是目前最可能的方式了把,呵呵,不過要注意她使dataTable的values直接使用了dataModel,她與seam的@dataModel是不兼容的,所以不能使用seam的@dataModel功能,需要使用get方式了。

    10.如果想使用ajax4jsf等ajax框架,你需要使用facelet,讓頁(yè)面成為標(biāo)準(zhǔn)的xhtml,記好了,不要寫了一大堆才發(fā)現(xiàn)這個(gè)問題。

    11.如果你在dataTable列表頁(yè)面使用了radio的話,你還想在列表上做一些link操作,一定要在操作上加入immediate=true,否則在沒有選擇radio的情況下她是不會(huì)讓你過去的。并且列表中要使用selectOneRadio,如果使用checkbox就要使用selectBooleanCheckbox.組件。

    12.對(duì)于doGet的方式請(qǐng)使用seam的<s:link>組件,<%=request.getContextPath() %>問題,提交引起的書簽問題都迎刃而解。

    13.如果你導(dǎo)入了其他頁(yè)面,而沒有使用facelet的話,那么導(dǎo)入的那個(gè)頁(yè)面就要完全符合jsf組件的渲染方式,混合html會(huì)解析不出來(lái)。反過來(lái)在主頁(yè)面應(yīng)該盡量多使用jsf標(biāo)記與html混合的方式,這樣可以使開發(fā)變得簡(jiǎn)單,盡管有時(shí)候jsf會(huì)很丟丑,你試試每個(gè)html組件都有個(gè)render屬性就知道了。jsf1.2已經(jīng)把混合的html作為一個(gè)output組件來(lái)輸出,可以和jsf組件兼容,是件好事。對(duì)于混合html這種方式,我想說(shuō)你關(guān)注的是jsf組件和模型的關(guān)系,而不一定頁(yè)面都得是jsf組件標(biāo)記。

    14.不要相信jsf運(yùn)行的速度慢,jsf雖然在樹形組件處理上,每一個(gè)階段都經(jīng)歷了遞歸遍歷,但是要相信jsf依然很快,我現(xiàn)在的系統(tǒng)很快,如果你使用后很慢那是項(xiàng)目產(chǎn)生了問題,而不是框架的產(chǎn)生了問題。

    15.相信jsf一定是下一代表現(xiàn)層的王者,這很重要。

    就這么多把,jsf的能多經(jīng)驗(yàn),我還在摸索當(dāng)中,有機(jī)會(huì)還會(huì)和大家交流
    fangshun1980@hotmail.com

    posted @ 2007-09-09 10:45 方順 閱讀(3237) | 評(píng)論 (12)編輯 收藏

    僅列出標(biāo)題  
    主站蜘蛛池模板: 久久久www成人免费毛片| 免费精品99久久国产综合精品| 日韩午夜理论免费TV影院| 国产精品亚洲产品一区二区三区| 精品国产亚洲第一区二区三区 | 中文字幕亚洲精品| 国产激情免费视频在线观看| 亚洲国产精久久久久久久| 人妻丰满熟妇无码区免费| 五月天网站亚洲小说| 最近中文字幕国语免费完整| 亚洲成人黄色在线观看| 国产香蕉九九久久精品免费| 亚洲jizzjizz少妇| 亚洲精品视频在线看| 中文字幕免费在线看线人动作大片| 亚洲色婷婷综合久久| 6080午夜一级毛片免费看 | 免费人成在线观看网站视频| 有码人妻在线免费看片| 亚洲精品乱码久久久久66| 亚洲免费视频网站| 国产精品亚洲精品| 免费又黄又爽又猛的毛片| 黄色网站软件app在线观看免费 | 免费a级毛片网站| 高清永久免费观看| 亚洲毛片免费观看| 国产精品成人免费综合| 国产精品免费大片一区二区| 亚洲视频欧洲视频| 四虎永久免费影院在线| 精品国产免费一区二区三区香蕉| 亚洲伦理一二三四| 亚洲午夜无码AV毛片久久| 久久w5ww成w人免费| 亚洲av午夜电影在线观看| 亚洲国产精品一区二区久久hs | 手机在线看永久av片免费| 青娱乐在线视频免费观看| 亚洲AV成人片色在线观看|