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

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

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

    周游世界

    喂馬, 劈柴, 周游世界

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      28 隨筆 :: 0 文章 :: 4 評(píng)論 :: 0 Trackbacks
    JSF for Nonbelievers: Clearing the FUD about JSF -- Richard Hightower
    來(lái)自:http://www-128.ibm.com/developerworks/library/j-jsf1/
    翻譯:zhouy
    --------------------------------------------------------------------------------
    恐懼、不確定和懷疑
    JSF 的觀念環(huán)繞著 JSF 技術(shù)已經(jīng)有一段時(shí)間了,我覺(jué)得是阻止這種觀念繼續(xù)曼延的時(shí)候了——或者至少在兩者這間取得平衡點(diǎn)。關(guān)于 JSF ,首當(dāng)其充的誤解,就是離不開(kāi)拖拽式所見(jiàn)即所得工具進(jìn)行 JSF 開(kāi)發(fā)。其二, JSF 不支持類(lèi)似 Struts MVC Model 2 框架。而最后一點(diǎn),也是困擾 JSF 開(kāi)發(fā)最大的一點(diǎn),就是關(guān)于其開(kāi)發(fā)困難度的說(shuō)法。

    在這個(gè)四小節(jié)的討論中,我將盡我所能,通過(guò)教你如何利用JSF進(jìn)行開(kāi)發(fā)這種最實(shí)際的方法,來(lái)消除上述所有三種誤解。事實(shí)上,如果你覺(jué)得JSF開(kāi)發(fā)是件困難的事,那么很有可能是因?yàn)槟銢](méi)有正確的使用它——幸運(yùn)的是要修正它并不難。我會(huì)讓你對(duì)JSF有一個(gè)大體的觀念,并且利用一個(gè)可工作的示例展示MVC和JSF的基本原理。在我們開(kāi)始所有介紹之前,先花一分鐘時(shí)間將事實(shí)不符的FUD區(qū)分清楚。

    不要相信FUD

    如前面提到的,關(guān)于JSF有三個(gè)大的誤解,其一便是JSF要求所見(jiàn)即所得工具進(jìn)行開(kāi)發(fā)工作。這是錯(cuò)誤的,就像許多Swing開(kāi)發(fā)人員不使用所見(jiàn)即所得工具構(gòu)建Swing應(yīng)用程序一樣,你不必需要所見(jiàn)即所得編輯器來(lái)構(gòu)建JSF應(yīng)用。事實(shí)上,不使用所見(jiàn)即所得工具來(lái)開(kāi)發(fā) JSF 會(huì)比傳統(tǒng)的Model 2框架如Struts和WebWork開(kāi)發(fā)來(lái)得簡(jiǎn)單。在稍后的章節(jié)中我會(huì)有詳細(xì)的解釋?zhuān)谶@里請(qǐng)記住:JSF開(kāi)發(fā)比Struts來(lái)得簡(jiǎn)單,即使不使用所見(jiàn)即所得工具!

    關(guān)于JSF的另一個(gè)誤解是,它不支持Model 2模型。現(xiàn)在,這種說(shuō)法只是部分正確。事實(shí)是Model 2是一種建立在Servlets基礎(chǔ)上的MVC瀑布模型版本。與Model 2面向無(wú)狀態(tài)協(xié)議(HTTP)所不同的是,JSF支持富MVC模型——一種與傳統(tǒng)的GUI應(yīng)用更加相似的模型。雖然MVC的基礎(chǔ)概念使得JSF框架的實(shí)現(xiàn)比其它框架困難,但在上層結(jié)構(gòu)上許多實(shí)現(xiàn)JSF的工作已經(jīng)為你做好,得到的結(jié)果是,付出減少,卻能夠獲得更多的回報(bào)。

    流傳最廣的關(guān)于JSF的誤解是在于JSF的開(kāi)發(fā)難度。我經(jīng)常從人們口中聽(tīng)到這樣的說(shuō)法,他們閱讀了大量的技術(shù)文檔,但是并沒(méi)有實(shí)際動(dòng)手去嘗試這項(xiàng)技術(shù),所以我認(rèn)為要消除這個(gè)慮慮很簡(jiǎn)單。如果你是通過(guò) JSF 浩瀚無(wú)邊的規(guī)格說(shuō)明來(lái)建立你對(duì)JSF的理解,那么這些東西肯定會(huì)使你受驚嚇。要明確的是,所有的這些規(guī)格本質(zhì)上是給實(shí)現(xiàn)工具使用的,而不是應(yīng)用程序開(kāi)發(fā)者。如前所述,JSF是為方便應(yīng)用程序開(kāi)發(fā)者而設(shè)計(jì)的。

    雖然從某種意義上說(shuō),JSF的組件基礎(chǔ)和事件驅(qū)動(dòng)的GUI式的開(kāi)發(fā)模型對(duì)于Java世界來(lái)說(shuō)是一種新鮮的事物,但是它其實(shí)早已在某些領(lǐng)域中存在了。Apple的WebObjects和ASP.net與JSF就十分的相似。Tapestry是一項(xiàng)開(kāi)源的Web組件框架,它與JSF所采用的方法不同,但也是一種基于Web GUI組件框型的技術(shù)。

    無(wú)論如何,關(guān)于FUD的討論或許可以終止。解決關(guān)于JSF的編見(jiàn)最快捷的方法便是正確地研究這門(mén)技術(shù),這正是我們稍后要做的事情。考慮到這或許是你第一次了解JSF,我將為你介紹它的總體概念。

    給JSF初學(xué)者

    類(lèi)似于Swing和AWT,JSF提供了一套標(biāo)準(zhǔn)和可重用的GUI組件。JSF被用來(lái)構(gòu)建Web應(yīng)用表層,它提供如下開(kāi)發(fā)優(yōu)勢(shì):

    • 動(dòng)作邏輯與表現(xiàn)邏輯的明顯區(qū)分
    • 有狀態(tài)事務(wù)的組件級(jí)別控制
    • 事件與服務(wù)端代碼的輕松綁定
    • UI組件及Web層觀念
    • 提供多樣的、標(biāo)準(zhǔn)的開(kāi)發(fā)商實(shí)現(xiàn)規(guī)則
    一個(gè)典型的JSF應(yīng)用包括以下幾個(gè)部分:
    • 供管理應(yīng)用狀態(tài)和動(dòng)作的JavaBeans組件
    • 事件驅(qū)動(dòng)開(kāi)發(fā)(通過(guò)與傳統(tǒng)GUI開(kāi)發(fā)類(lèi)似的監(jiān)聽(tīng)器來(lái)實(shí)現(xiàn))
    • 展示MVC樣式的頁(yè)面,通過(guò)JSF組件樹(shù)引用視圖
    雖然你將需要克服使用JSF過(guò)程中的觀念上的困難,但是這些努力都將是值得的。JSF的組件狀態(tài)管理,方便的用戶(hù)輸入校驗(yàn),小粒度,組件基礎(chǔ)的事件處理及方便的可擴(kuò)展框架將使你的Web開(kāi)發(fā)便得簡(jiǎn)單。我將在接下來(lái)的幾章中用最詳細(xì)的解釋說(shuō)明這些最重要的特征。

    組件基礎(chǔ)的框架模式

    JSF為標(biāo)準(zhǔn)HTML中每個(gè)可用的輸入域提供了組件標(biāo)簽,你也可以為你應(yīng)用中的特殊目的定義自己的組件,或者也可以將多項(xiàng)HTML組件組合起來(lái)成為一個(gè)新的組合——例如一個(gè)數(shù)據(jù)采集組件可以包含三個(gè)下拉菜單。JSF組件是有狀態(tài)的,組件的狀態(tài)由JSF框架來(lái)提供,JSF用組件來(lái)處理HTML響應(yīng)。

    JSF的組件集包含事件發(fā)布模型、一個(gè)輕量級(jí)的IoC容量、擁有其它普遍的GUI特征的組件,包括可插入的渲染、服務(wù)器端校驗(yàn)、數(shù)據(jù)轉(zhuǎn)換、頁(yè)面導(dǎo)航控制等等。作為一種基于組件的框架,JSF極具可配置性和可護(hù)展性。大部分的JSF功能,比如導(dǎo)航和受管bean查詢(xún),可以被可插入組件所替換。這樣的插入程度給開(kāi)發(fā)人員構(gòu)建Web應(yīng)用GUI時(shí)提供了極大的彈性,允許開(kāi)發(fā)人員將其它基于組件的技術(shù)應(yīng)用于JSF的開(kāi)發(fā)過(guò)程中來(lái)。比如說(shuō),你可以將JSF的內(nèi)嵌IoC框架替換為更加全能的Spring的IoC/AOP以供受管bean查詢(xún)。

    JSF和JSP技術(shù)

    一個(gè)JSF應(yīng)用的用戶(hù)表層被包含在JSP(JavaServer Pages)頁(yè)面中。每個(gè)JSP頁(yè)面包含有JSF組件,這些組件描繪了GUI功能。你可以在JSP頁(yè)面里使用 JSF 定制標(biāo)簽庫(kù)來(lái)渲染UI組件,注冊(cè)事件句柄,實(shí)現(xiàn)組件與校驗(yàn)器的交互及組件與數(shù)據(jù)轉(zhuǎn)換器的交互等等。

    那就是說(shuō),JSF不是固定與JSP技術(shù)相關(guān)聯(lián)。事實(shí)上,JSF標(biāo)簽僅僅引用組件以實(shí)現(xiàn)顯示的目的。你會(huì)發(fā)現(xiàn)當(dāng)你第一次修改一個(gè)JSP頁(yè)面中某一JSF組件的屬性,在重新載入頁(yè)面的時(shí)候并沒(méi)有發(fā)生應(yīng)有的變化。這是因?yàn)闃?biāo)簽在它自己的當(dāng)前狀態(tài)中進(jìn)行查詢(xún),如果組件已經(jīng)存在,標(biāo)簽就不會(huì)改變它的狀態(tài)。組件模型允許控制代碼改變一個(gè)組件的狀態(tài)(例如將一個(gè)輸入域置為不可用),當(dāng)視圖被展現(xiàn)的時(shí)候,組件樹(shù)的當(dāng)前狀態(tài)也隨著一覽無(wú)余。

    一個(gè)典型的JSF應(yīng)用在UI層無(wú)需任何的Java代碼,只需要很少的一部份JSTL EL( JSP 標(biāo)準(zhǔn)標(biāo)簽庫(kù),表達(dá)式語(yǔ)言)。前面已經(jīng)提及,有非常多IDE工具可以幫助我們構(gòu)建JSF應(yīng)用,并且有越來(lái)越多的第三方JSF GUI組件市場(chǎng)。不使用所見(jiàn)即所得工具來(lái)編寫(xiě)JSF也是可行的。

    JSF和MVC

    JSF技術(shù)是在多年Java平臺(tái)上的Web開(kāi)發(fā)技術(shù)的總結(jié)的產(chǎn)物。這種趨勢(shì)起源于JSP。JSP是一種很好的表現(xiàn)層,但同時(shí)它容易將Java代碼與HTML頁(yè)面混淆起來(lái)。另一個(gè)不好的原因與Model 1架構(gòu)有關(guān),它使得開(kāi)發(fā)人員通過(guò)使用 <jsp:useBean> 標(biāo)簽將許多原本應(yīng)該在后端處理的代碼引入到Web頁(yè)面中來(lái)。這種方法在簡(jiǎn)單的Web應(yīng)用中可以運(yùn)行得很好,但許多Java開(kāi)發(fā)者不喜歡這種類(lèi)似C++的靜態(tài)引入組合方式,所以Model 2架構(gòu)隨之被引進(jìn)。

    本質(zhì)上,Model 2架構(gòu)是MVC Web應(yīng)用的一種瀑布模型版本。在Model 2架構(gòu)中控制器通過(guò)Servlets來(lái)表現(xiàn),顯示層則通過(guò)JSP頁(yè)面來(lái)展現(xiàn)。Struts是一種最簡(jiǎn)單的Model 2實(shí)現(xiàn),它使用Actions取代了Servlets。在Struts中應(yīng)用的控制邏輯與數(shù)據(jù)層(通過(guò)ActionForms來(lái)展現(xiàn))相分離。反對(duì)Struts的主要的不滿(mǎn)在于,Struts更多偏向程序化,而非面向?qū)ο蟆ebWork和Spring MVC是Model 2的另外兩種框架,它們比起Struts更大的改進(jìn)在于盡量減少程序化,但是兩者都沒(méi)有Struts普及。另外兩者也不像JSF般提供組件模型。

    大多數(shù)Model 2框架真正的因素在于它們的事件模型顯得過(guò)于單薄,留下了太多的工作需要開(kāi)發(fā)人員自己來(lái)處理。一個(gè)富事件模型使多數(shù)用戶(hù)所希望的交互變得簡(jiǎn)單。許多Model 2技術(shù)就像JPS一樣,很容易將HTML布局及格式與GUI標(biāo)簽相混合,在表現(xiàn)上不像真正的組件。而一些Model 2的架構(gòu)(如Struts)錯(cuò)誤地將表現(xiàn)與狀態(tài)分離,便得許多Java開(kāi)發(fā)人員感覺(jué)他們像是在編寫(xiě)COBOL程序。

    富MVC環(huán)境

    JSF提供一種組件模型及比其它Model 2實(shí)現(xiàn)更為豐富的MVC環(huán)境。本質(zhì)上說(shuō),JSF比Model 2架構(gòu)更接近真正的MVC開(kāi)發(fā)環(huán)境,雖然它仍然屬于無(wú)狀態(tài)協(xié)議。JSF能夠構(gòu)建比起其它Model 2框架更精彩的事件驅(qū)動(dòng) GUI 。JSF提供一系列事件選項(xiàng)如menu選項(xiàng)的selected事件,button的clicked事件等等,這與在其它Model 2框架中更多地依賴(lài)簡(jiǎn)單的“request received”不同。

    JSF的易于翻轉(zhuǎn)的事件模型允許應(yīng)用程序更少地依賴(lài)HTTP實(shí)現(xiàn)細(xì)節(jié),簡(jiǎn)化你的開(kāi)發(fā)量。JSF改善了傳統(tǒng)Model 2架構(gòu),它更容易將表現(xiàn)層和業(yè)務(wù)層移出控制器,并將業(yè)務(wù)邏輯從JSP頁(yè)面中移出。事實(shí)上,簡(jiǎn)單的控制器類(lèi)根本無(wú)需與JSF相關(guān)聯(lián),方便了對(duì)控制器類(lèi)的測(cè)試。與真正的MVC架構(gòu)不同,JSF不會(huì)在多于一個(gè)視點(diǎn)上發(fā)出多條事件,我們?nèi)匀皇窃谔幚硪粋€(gè)無(wú)狀態(tài)的協(xié)議,這使得這一點(diǎn)變得無(wú)關(guān)緊要。系統(tǒng)事件對(duì)一個(gè)視圖的變動(dòng)或更新通常來(lái)自于用戶(hù)的請(qǐng)求。

    JSF的MVC實(shí)現(xiàn)細(xì)節(jié)

    在JSF的MVC實(shí)現(xiàn)中,作為映射的backing bean在視圖和模型間扮演著協(xié)調(diào)的作用。正因如此,在backing bean里限制業(yè)務(wù)邏輯和持久層邏輯就顯得猶為重要。一種普遍的做法是將業(yè)務(wù)邏輯置入應(yīng)用模型中。這樣的話(huà)backing bean仍會(huì)映射模型對(duì)象以供視圖顯示。另一種選擇是將業(yè)務(wù)邏輯放入業(yè)務(wù)代理——一種與模型相作用的表層。

    與JSP技術(shù)不同,JSF的視圖實(shí)現(xiàn)是一種有狀態(tài)組件模型。JSF的視圖由兩部分組成:根視圖和JSP頁(yè)面。根視圖是UI組件的集合,它負(fù)責(zé)維護(hù)UI的狀態(tài)。就如像Swing和AWT,JSF組件使用組合式設(shè)計(jì)模式來(lái)管理組件樹(shù),用按鈕來(lái)管理事件句柄及動(dòng)作方法。

    Figure 1 通過(guò)MVC角度來(lái)透析的示例


    ?

    一個(gè) JSF 例子

    在文章剩余的章節(jié)里,我將專(zhuān)注于構(gòu)建一個(gè) JSF 應(yīng)用的過(guò)程。這個(gè)例子是 JSF 技術(shù)的一個(gè)非常簡(jiǎn)單的展現(xiàn),主要表現(xiàn)在以下幾個(gè)方面:

    • 如何設(shè)置 JSF 應(yīng)用程序的格局
    • 如何為 JSF 配置 web.xml 文件
    • 如何為程序配置 faces-config.xml 文件
    • 編寫(xiě)模型(即 backing bean
    • 利用 JSP 技術(shù)構(gòu)建視圖
    • 利用傳統(tǒng)標(biāo)簽庫(kù)在根視圖框建組件樹(shù)
    • Form 的默認(rèn)校驗(yàn)規(guī)則

    例子是一個(gè)簡(jiǎn)單的計(jì)算器程序,使目標(biāo)用戶(hù)能夠輸入兩個(gè)數(shù)并計(jì)算。因此頁(yè)面上有兩個(gè)文本域,兩個(gè)標(biāo)簽,兩處錯(cuò)誤提示和一個(gè)提交按鈕。文本域用來(lái)輸入數(shù)字,標(biāo)簽用來(lái)標(biāo)示輸入的文本域,錯(cuò)誤提示用來(lái)顯示文本域中的輸入在校驗(yàn)或數(shù)據(jù)轉(zhuǎn)換時(shí)出現(xiàn)的錯(cuò)誤。總共有三個(gè) JSP 頁(yè)面: index.jsp 用來(lái)重定向到 calculator.jsp 頁(yè)面; calculator.jsp 用來(lái)顯示上面提及的 GUI result.jsp 用來(lái)顯示最后結(jié)果。一個(gè)受管 bean CalculatorController 作為 calculator.jsp result.jsp backing bean

    ? Figure 2 示例程序的第二張 MVC 視圖


    構(gòu)建應(yīng)用
    ?
    為了構(gòu)建計(jì)算器程序,你需要如下步驟:

    1. ? 收集 web.xml faces-config.xml 文件,可以在下面的示例源代碼中找到。
    2. web.xml 中聲明 Faces Servlet Faces Servlet 映射。
    3. web.xml 中指定 faces-config.xml
    4. faces-config.xml 中聲明受管于 JSF bean
    5. faces-config.xml 中聲明導(dǎo)航規(guī)則。
    6. 構(gòu)建模型對(duì)象 Calculator
    7. CalculatorController Calculator 交互。
    8. 創(chuàng)建 index.jsp 頁(yè)面。 ?
    9. 創(chuàng)建 calculator.jsp 頁(yè)面。
    10. 創(chuàng)建 results.jsp 頁(yè)面。

    聲明 Faces Servlet Servlet 映射
    ?

    為了使用 Faces ,你需要在 web.xml 中裝載 Faces Servlet 如下:

    <!-- Faces Servlet -->
    <servlet>
    ? <servlet-name>Faces Servlet</servlet-name>
    ? <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    ? <load-on-startup>1</load-on-startup>
    </servlet>

    這和大多數(shù)web.xml描述文件類(lèi)似,所不同的是將request的掌握權(quán)轉(zhuǎn)向JSF Servlet,而非自定義的Servlet。所有請(qǐng)求引用了f:viewJSP文件的request都將通過(guò)此Servlet。因此需要增加相應(yīng)的映射,并且將允許使用JSFJSP技術(shù)通過(guò)映射裝載進(jìn)來(lái)。

    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
    ??? <servlet-name>Faces Servlet</servlet-name>
    ??? <url-pattern>/calc/*</url-pattern>
    </servlet-mapping>

    以上配置告知Faces Servlet容器將所有符合/calc/的請(qǐng)求都轉(zhuǎn)給Faces Servlet處理。這使得JSF能夠初始化JSF內(nèi)容和根視圖。

    定義faces-config.xml文件

    如果你將你的faces配置文件命名為faces-config.xml并將其放置在WEB-INF目錄下,Faces Servlet會(huì)查找到它并自動(dòng)使用它。或者你也可以通過(guò)web.xml?中的一個(gè)初始化參數(shù)裝載一個(gè)或多個(gè)應(yīng)用配置文件——javax.faces.application.CONFIG_FILES——通過(guò)逗號(hào)將作為參數(shù)的文件列表分隔開(kāi)來(lái)。或許你會(huì)使用第二種方法為所有的JSF應(yīng)用程序作配置。

    聲明bean管理

    接著是聲明哪個(gè)beanJSF GUI組件所使用。在示例中只有一個(gè)受管bean,在faces-config.xml中配置如下:
    <faces-config>
    ?? ?...
    ? <managed-bean>
    ??? <description>
    ????? The "backing file" bean that backs up the calculator webapp
    ??? </description>
    ??? <managed-bean-name>CalcBean</managed-bean-name>
    <managed-bean-class>
    ?? ?com.arcmind.jsfquickstart.controller.CalculatorController
    </managed-bean-class>
    ??? <managed-bean-scope>session</managed-bean-scope>
    ? </managed-bean>
    </faces-config>

    上面的配置告知JSF要往JSF環(huán)境中增加一個(gè)叫做CalcBeanbean,你也可以把受管bean取任何名字。Bean已經(jīng)聲明了,然后你要做的就是為應(yīng)用定義導(dǎo)航規(guī)則。

    定義導(dǎo)航規(guī)則

    這樣一個(gè)簡(jiǎn)單的應(yīng)用,你只需使導(dǎo)航規(guī)則從calculator.jspresult.jsp頁(yè)面即可。如下:

    <navigation-rule>
    ? <from-view-id>/calculator.jsp</from-view-id>
    ? <navigation-case>
    ??? <from-outcome>success</from-outcome>
    ??? <to-view-id>/results.jsp</to-view-id>
    ? </navigation-case>
    </navigation-rule>

    上面的代碼表明,如果一個(gè)動(dòng)作從/calculator.jsp頁(yè)面返回邏輯輸出為“success”,那么它將用戶(hù)轉(zhuǎn)向/result.jsp頁(yè)面。

    ?視計(jì)模型對(duì)象

    ?由于我們的目標(biāo)是介紹如何開(kāi)始JSF,所以我將模型對(duì)象設(shè)計(jì)得非常簡(jiǎn)單。這個(gè)模型包含在一個(gè)對(duì)象里,如Listing 1所示。

    ?Listing 1. The Calculator app's model object

    package com.arcmind.jsfquickstart.model;

    /**
    ?* Calculator
    ?*
    ?* @author Rick Hightower
    ?* @version 0.1
    ?*/
    public class Calculator {
    ??? //~Methods------------------------------------------------
    ??? /**
    ???? * add numbers.
    ???? *
    ???? * @param a first number
    ???? * @param b second number
    ???? *
    ???? * @return result
    ???? */
    ??? public int add(int a, int b) {
    ??????? return a + b;
    ??? }

    ??? /**
    ???? * multiply numbers.
    ???? *
    ???? * @param a first number
    ???? * @param b second number
    ???? *
    ???? * @return result
    ???? */
    ??? public int multiply(int a, int b) {
    ??????? return a * b;
    ??? }
    }

    這樣,業(yè)務(wù)邏輯就全部建立了。下一步便是將其顯示在
    Web表現(xiàn)層上。

    ?結(jié)合模型和視圖

    ?控制器的目的就是將模型與視圖結(jié)合在一起。控制器對(duì)象的一個(gè)作用就是保持模型與視圖的不可知論。(?)如同你在下面所看到的,控制器定義了三個(gè)JavaBeans屬性,通過(guò)這些屬些控制輸入和輸出結(jié)果。這些屬性是:results(作為輸出)、firstNumber(作為輸入)、secondNumber(作為輸入)。Listing 2CalculatorController的代碼。

    ?Listing 2. The CalculatorController

    package com.arcmind.jsfquickstart.controller;

    import com.arcmind.jsfquickstart.model.Calculator;

    /**
    ?* Calculator Controller
    ?*
    ?* @author $author$
    ?* @version $Revision$
    ?*/
    public class CalculatorController {
    ??? //~ Instance fields --------------------------------------------------------

    ??? /**
    ???? * Represent the model object.
    ???? */
    ??? private Calculator calculator = new Calculator();

    ??? /** First number used in operation. */
    ??? private int firstNumber = 0;

    ??? /** Result of operation on first number and second number. */
    ??? private int result = 0;

    ??? /** Second number used in operation. */
    ??? private int secondNumber = 0;

    ??? //~ Constructors -----------------------------------------------------------

    ??? /**
    ???? * Creates a new CalculatorController object.
    ???? */
    ??? public CalculatorController() {
    ??????? super();
    ??? }

    ??? //~ Methods ----------------------------------------------------------------

    ??? /**
    ???? * Calculator, this class represent the model.
    ???? *
    ???? * @param aCalculator The calculator to set.
    ???? */
    ??? public void setCalculator(Calculator aCalculator) {
    ??????? this.calculator = aCalculator;
    ??? }

    ??? /**
    ???? * First Number property
    ???? *
    ???? * @param aFirstNumber first number
    ???? */
    ??? public void setFirstNumber(int aFirstNumber) {
    ??????? this.firstNumber = aFirstNumber;
    ??? }

    ??? /**
    ???? * First number property
    ???? *
    ???? * @return First number.
    ???? */
    ??? public int getFirstNumber() {
    ??????? return firstNumber;
    ??? }

    ??? /**
    ???? * Result of the operation on the first two numbers.
    ???? *
    ???? * @return Second Number.
    ???? */
    ??? public int getResult() {
    ??????? return result;
    ??? }

    ??? /**
    ???? * Second number property
    ???? *
    ???? * @param aSecondNumber Second number.
    ???? */
    ??? public void setSecondNumber(int aSecondNumber) {
    ??????? this.secondNumber = aSecondNumber;
    ??? }

    ??? /**
    ???? * Get second number.
    ???? *
    ???? * @return Second number.
    ???? */
    ??? public int getSecondNumber() {
    ??????? return secondNumber;
    ??? }

    ??? /**
    ???? * Adds the first number and second number together.
    ???? *
    ???? * @return next logical outcome.
    ???? */
    ??? public String add() {
    ???????
    ??????? result = calculator.add(firstNumber, secondNumber);

    ??????? return "success";
    ??? }

    ??? /**
    ???? * Multiplies the first number and second number together.
    ???? *
    ???? * @return next logical outcome.
    ???? */
    ??? public String multiply() {

    ??????? result = calculator.multiply(firstNumber, secondNumber);
    ??? ???
    ??????? return "success";
    ??? }
    }

    請(qǐng)注意,在
    Listing 2中乘法和加法都返回“success”。“success”表明一個(gè)邏輯輸出,它不是保留字,它是與faces-config.xml的導(dǎo)航規(guī)則相結(jié)合的,通過(guò)增加或定義操作執(zhí)行,頁(yè)面將轉(zhuǎn)向result.jsp

    ?這樣,你已經(jīng)完成了后臺(tái)代碼工作。接下來(lái)我們將定義JSP頁(yè)面及組件樹(shù)以展示應(yīng)用視圖。

    ?創(chuàng)建index.jsp頁(yè)面

    ?Index.jsp的目的是保證/calculator.jsp頁(yè)面被正確的裁入JSF內(nèi)容中,使得頁(yè)面可以找到正確的根視圖。

    <jsp:forward page="/calc/calculator.jsp" />

    ?這個(gè)頁(yè)面全部所做的工作便是將用戶(hù)重定向到/calc/calculator.jsp頁(yè)面。這樣便將calculator.jsp頁(yè)面導(dǎo)向JSF內(nèi)容中,使得JSF可以找到根視圖。

    ?創(chuàng)建calculator.jsp頁(yè)面

    ?Calculator.jsp是整個(gè)計(jì)算器應(yīng)用程序的中心視圖。這個(gè)頁(yè)面獲取用戶(hù)輸入的兩個(gè)數(shù)字,如Figure 3所示。

    Figure 3. The Calculator page
    Calculator page

    ?

    這一頁(yè)較為復(fù)雜,我將一步一步進(jìn)行講解。首先你需要聲明供JSF使用的標(biāo)簽庫(kù):

    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

    上述代碼告訴
    JSP引擎你將使用兩個(gè)JSF標(biāo)簽庫(kù):htmlcoreHtml標(biāo)簽庫(kù)包含所有與forms和其它HTML規(guī)范有關(guān)的標(biāo)簽。Core標(biāo)簽庫(kù)包含所有邏輯、校驗(yàn)、控制等JSF標(biāo)簽。

    ?一旦將頁(yè)面展示在普通的HTML中,你會(huì)告訴JSF系統(tǒng)你將使用JSF來(lái)管理你的組件。通過(guò)使用<f:view>標(biāo)簽來(lái)實(shí)現(xiàn)這點(diǎn),它會(huì)告知容器你將使用JSF來(lái)管理所有包含在它里面的組件。

    ?少了<f:view>JSF將無(wú)法構(gòu)建組件樹(shù),稍后也無(wú)法在已經(jīng)創(chuàng)建起來(lái)的組件樹(shù)中進(jìn)行查詢(xún)。通過(guò)以下代碼使用<f:view>

    <f:view>
    ? <h:form id="calcForm">
    ???? ...?? ?
    ? </h:form>
    </f:view>

    上面的第一行是<f:view>的聲明,告知容器它受管于JSF。下一行是<h:form>標(biāo)簽,它告知JSF你需要在此建一個(gè)HTML FORM。在位于FORM組件內(nèi)的組件容器的語(yǔ)法渲染期間,所有的組件將會(huì)被問(wèn)詢(xún)自動(dòng)渲染,這樣它們將會(huì)生成標(biāo)準(zhǔn)的HTML代碼。

    接下來(lái),你告知JSFFORM里所需的其它組件。在<h:form>中定義了一個(gè)panelGridpanelGrid是一個(gè)組合組件——也就是一個(gè)組件里包含有其它的組件。panelGrid定義其它組件的布局,Listing 3顯示如何定義panelGrid的代碼:

    Listing 3. Declaring the panelGrid

    <h:panelGrid columns="3">
    ? <h:outputLabel value="First Number" for="firstNumber" />
    ? <h:inputText id="firstNumber" value="#{CalcBean.firstNumber}" required="true" />
    ? <h:message for="firstNumber" />???
    ? <h:outputLabel value="Second Number" for="secondNumber" />
    ? <h:inputText id="secondNumber" value="#{CalcBean.secondNumber}" required="true" />
    ? <h:message for="secondNumber" />
    </h:panelGrid>

    屬性columns被定義為3表明所有組件將被布置在擁有3列空間的格局中。我們?cè)?/span>panelGrid中加入了6個(gè)組件,共占2行。每一行包含一個(gè)outputLabel,一個(gè)inputText和一條messageLabelmessage都和inputText組件關(guān)聯(lián),因此當(dāng)一個(gè)校驗(yàn)錯(cuò)誤或或誤信息關(guān)聯(lián)到textField時(shí),信息將會(huì)顯示在message組件上。兩個(gè)文本輸入域都要求有,如果在提交的時(shí)候檢測(cè)到無(wú)值,錯(cuò)誤信息將會(huì)被創(chuàng)建,控制也將會(huì)轉(zhuǎn)到這個(gè)視圖來(lái)。

    注意到兩個(gè)inputFields都使用一條JSF表達(dá)式來(lái)做數(shù)值綁定。乍一看這很像一條JSTL表達(dá)式。但是,JSF表達(dá)式確實(shí)與綁定著后臺(tái)代碼相應(yīng)字段的輸入域相關(guān)聯(lián)。這種關(guān)聯(lián)是反向的,如果firstNumber100,那么在form顯示的時(shí)候100也會(huì)被顯示。同樣,如果用戶(hù)提交一個(gè)有效的值,例如200,那么200也將作為firstNumber的新值。

    一個(gè)更加實(shí)用的目的是,后臺(tái)代碼通過(guò)綁定模型對(duì)象的屬性的值到輸入域中,從而將模型對(duì)象展現(xiàn)出來(lái)。你將在此節(jié)稍后看到關(guān)于此目的的例子。

    除了輸入域,calForm通過(guò)panelGroup中的兩個(gè)commandButton與兩個(gè)動(dòng)作關(guān)聯(lián):

    <h:panelGroup>
    ??? <h:commandButton id="submitAdd" action="#{CalcBean.add}"? value="Add" />
    ??? <h:commandButton id="submitMultiply" action="#{CalcBean.multiply}" value="Multiply" />
    </h:panelGroup>

    panelGroup的概念與panelGrid很相似,除了它們顯示方式的不同。命令按鈕利用action=”#{CalcBean.add}”將按鈕與后臺(tái)動(dòng)作綁定在一起。因此當(dāng)這個(gè)form通過(guò)這個(gè)按鈕提交的時(shí)候,相關(guān)聯(lián)的方法便開(kāi)始執(zhí)行。

    創(chuàng)建results.jsp頁(yè)面

    Results.jsp頁(yè)面是用來(lái)顯示最后計(jì)算結(jié)果。如Listing 4所示:

    Listing 4. The results.jsp page

    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    ...
    <f:view>
    ? First Number: <h:outputText id="firstNumber" value="#{CalcBean.firstNumber}"/>
    ? <br />
    ? Second Number: <h:outputText id="secondNumber" value="#{CalcBean.secondNumber}"/>
    ? <br />
    ? Result: <h:outputText id="result" value="#{CalcBean.result}"/>
    ? <br />
    </f:view>

    Results.jsp
    是一個(gè)相對(duì)簡(jiǎn)單的頁(yè)面,將加法運(yùn)算的結(jié)果顯示給用戶(hù)。通過(guò)<h:outputText>標(biāo)簽來(lái)完成這一功能。<h:outputText>標(biāo)簽帶有idvalue屬性,value屬性輸出值,它在渲染的時(shí)候?qū)⒈划?dāng)作string看待。Value屬性通過(guò)JSF將要輸出的值與后臺(tái)代碼的屬性綁定在一起。

    ?運(yùn)行程序!

    運(yùn)行war文件所映射的程序。Index.jsp頁(yè)面將調(diào)用calculator.jsp,如果你在firstNumber域或secondNumber域中輸入非法文本(如“abc”)提交,你將返回到/calculator.jsp視圖并且相應(yīng)的錯(cuò)誤信息將會(huì)顯示在頁(yè)面上。如果你將firstNumbersecondNumber放空提交你也將會(huì)獲得相應(yīng)的錯(cuò)誤結(jié)果。由此可以看出在JSF許多校驗(yàn)幾乎是自動(dòng)定義,只要你將輸入域定義為required并且綁定相應(yīng)的int屬性的字段即可。

    Figure 4顯示應(yīng)用程序如何處理校驗(yàn)和數(shù)據(jù)轉(zhuǎn)換數(shù)據(jù)。

    Figure 4. Validation and data conversion errors


    ?

    總結(jié)

    在這篇關(guān)于JSF的介紹中是否使你有些頭暈?不用擔(dān)心,你已經(jīng)跨過(guò)了最壞的一道坎。了解JSF的框架概念是這場(chǎng)戰(zhàn)役的一半,有過(guò)之而無(wú)不及,而且你將會(huì)很快意識(shí)到它的價(jià)值。

    如果在閱讀的過(guò)程中你想象使用Struts實(shí)現(xiàn)上述代碼會(huì)更加簡(jiǎn)單,我估計(jì)它會(huì)耗費(fèi)至少兩倍精力。用Struts構(gòu)建同樣的應(yīng)用,你需要為兩個(gè)按鈕創(chuàng)建兩個(gè)action類(lèi),各自需要自己的對(duì)應(yīng)的動(dòng)作映射。而且需要一個(gè)動(dòng)作映射來(lái)裝載首頁(yè)(假設(shè)你遵守Model 2的建議)。另外,模仿JSF默認(rèn)的錯(cuò)誤獲取和校驗(yàn)機(jī)制,你需要為Struts配置校驗(yàn)框架或者實(shí)現(xiàn)在ActionForm中實(shí)現(xiàn)等值的validate方法。你還必須在Struts配置中定義DynaValidatorForm或者建立一個(gè)ActionForm重寫(xiě)validate方法,或者使用ValidatorForm的子類(lèi)。最終,你或許(必須)需要為所有的action定義forward或者全局forward

    不止雙倍的代碼工作,Struts對(duì)于初學(xué)者來(lái)說(shuō)意味著需要花費(fèi)更多的精力。我之所以知道這點(diǎn),是因?yàn)槲覍?xiě)過(guò)關(guān)于StrutsJSF課程的教材并且為我的學(xué)員們上過(guò)課。開(kāi)發(fā)人員通常非常容易掌握JSF,但在學(xué)習(xí)Struts的過(guò)程中卻倍受折磨。我相信更多有遠(yuǎn)見(jiàn)的人選擇JSF,而非Struts。直覺(jué)上說(shuō),JSF更加合理。Struts已經(jīng)被擱置,JSF被列入技術(shù)清單。在我的書(shū)中,JSF開(kāi)發(fā)過(guò)程是簡(jiǎn)便的,并且比Struts更具有生產(chǎn)率。

    這是JSF系列的第一篇文章的總結(jié)。在下一篇文章里我會(huì)繼續(xù)這篇文章的話(huà)題,內(nèi)容覆蓋JSFrequest處理生命周期,指明生命周期中同一應(yīng)用程序的不同部分。我還將介紹immediate event handling的概念,并且讓你對(duì)JSF的組件事件模型有更全面了解,包括關(guān)于許多內(nèi)嵌組件的討論。我還將談?wù)動(dòng)嘘P(guān)JSFJavaScript相結(jié)合的話(huà)題,請(qǐng)關(guān)注下個(gè)月的文章。

    posted on 2006-07-17 20:54 周游世界 閱讀(531) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JSF翻譯

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 伊人免费在线观看高清版| 免费无遮挡无码视频在线观看| 亚洲乱码一二三四五六区| 国产亚洲精品成人AA片| 色欲aⅴ亚洲情无码AV| 国产中文字幕在线免费观看| 99免费在线观看视频| 妞干网免费观看视频| 亚洲成a人片在线观看国产| 亚洲精品V欧洲精品V日韩精品| 亚洲天堂男人天堂| 国产99在线|亚洲| 五月天国产成人AV免费观看| 久久免费精品一区二区| 免费AA片少妇人AA片直播| 国产又大又粗又硬又长免费 | 成人免费AA片在线观看| 四虎永久免费影院在线| 精品亚洲综合久久中文字幕| 日本亚洲精品色婷婷在线影院| 黄色a级免费网站| 99re在线免费视频| 日本免费一区尤物| 在线亚洲午夜理论AV大片| xxx毛茸茸的亚洲| 一出一进一爽一粗一大视频免费的| 国产精品免费一区二区三区四区| a毛片基地免费全部视频| 国产亚洲成归v人片在线观看| 亚洲国产成人资源在线软件| 一级毛片a女人刺激视频免费| 成人午夜免费福利视频| 亚洲国产精品13p| jlzzjlzz亚洲jzjzjz| 中文字幕在线免费视频| 噼里啪啦电影在线观看免费高清 | 久久夜色精品国产亚洲av| 亚洲熟妇色自偷自拍另类| 一级毛片免费毛片毛片| 国产1024精品视频专区免费| 亚洲人成人无码网www电影首页|