AJAX和Web開發新技術DynamicFaces簡介

來源:互聯網
上載者:User
Project Dynamic Faces是數個擴充JavaServer Faces技術的的項目之一。Project Dynamic Faces是一個創新型的項目,提供了向基於JavaServer Faces技術的應用軟體增添Ajax功能的方法。它使我們能夠讓應用軟體已經在使用的任何JavaServer Faces組件支援Ajax功能。我們無需對組件進行修改就能夠使它們支援Ajax,我們也無需對應用軟體進行任何修改就可以使它具有Ajax的魔力。

  要使應用軟體具有Ajax魔力,我們必須首先確定應用中希望Ajax功能更新的網頁部分。象基於JavaServer Faces技術的開發人員瞭解的那樣,JavaServer Faces網頁是由組件樹表示的。利用Dynamic Faces,我們能夠確定組件樹中的哪個組件會受益於非同步更新。就象使用Ajax更新代表網頁的HTML DOM樹的一部分那樣,我們使用Dynamic Faces更新代表JavaServer Faces網頁的組件樹的一部分。因此,Dynamic Faces機制對於Ajax和JavaServer Faces開發人員而言是熟悉的。

  更重要的是,Dynamic Faces使用JavaServer Faces組件模式,使我們能夠以一種更有效方式利用Ajax功能。由於組件模式的協作特性,一些網頁組件上的JavaScript事件能夠觸發該網頁上任何數量的其它組件的非同步更新。Dynamic Faces使得這些非同步更新只是向伺服器發送的一次Ajax請求的結果,而不是導致每次非同步更新的Ajax請求的結果。

  Dynamic Faces還利用JavaServer Faces組件模式有效地管理客戶機端和伺服器端的狀態。當Dynamic Faces更新客戶機端上的組件狀態時,它更新的只是已經改變的組件而不是整個樹的狀態。最好的一點是Dynamic Faces在後台完成所有這些操作,而且是以一種與JavaServer Faces技術的生命週期完全一致的方式完成的。

  除了簡化嚮應用軟體增添Ajax功能外,Dynamic Faces還向我們提供了增添Ajax功能的方法的靈活性。這篇文章將討論利用Dynamic Faces使應用軟體更具互動性和活力的三種方法:

  ·利用Dynamic Faces提供的定製ajaxZone標籤確定組件樹中需要被Ajax化的部分。

  ·利用Dynamic Faces提供的JavaScript庫向單個組件增添Ajax功能。

  ·在一個網頁中增添支援Ajax的組件,例如jMaki widget。

  在學習這些技術前,我們先來看看應用軟體如何才能使用Dynamic Faces技術。

  開發利用Dynamic Faces的應用軟體

  通過向一個標準的JavaServer Faces 1.2實現中增添Ajax功能,Dynamic Faces利用了JavaServer Faces技術的已耗用時間庫的可擴充性。 Dynamic Faces的核心是定製的Lifecycle和ViewRoot實現。這二個實現是JavaServer Faces技術提供的標準Lifecycle和ViewRoot實現的擴充, 一個標準的Lifecycle對象代表JavaServer Faces生命週期的一個執行個體,一個標準的ViewRoot對象代表一個組件樹的根。聯合使用定製Lifecycle對象和定製ViewRoot對象,使JavaServer Faces生命週期能夠處理Ajax事務,在無需對整個網頁更新的情況下重新顯示組件樹的一部分。這些定製實現服從於不支援Ajax請求的標準實現。

  為了使JavaServer Faces技術已耗用時間庫知道定製Lifecycle對象的存在,我們必須在配置描述器中利用一個初始化參數向FacesServlet執行個體報告該對象。

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<init-param>
<param-name>javax.faces.LIFECYCLE_ID</param-name>
<param-value>com.sun.faces.lifecycle.PARTIAL</param-name>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

  此外,我們還必須將Dynamic Faces依賴的Java Archive(JAR)檔案添加到應用軟體的web archive(WAR)檔案的lib目錄中。因為Dynamic Faces是基於Java Platform Enterprise Edition 5(Java EE 5)的,我們所需要的幾乎所有依賴關係都已經存在。最後一個依賴是Shale Remoting,Dynamic Faces利用它從Java類路徑中載入JavaScript檔案和其它資源。 Shale Remoting依賴於commons-logging,因此我們必須嚮應用軟體提供commons-logging。

  最後,我們必須在使用它的每個網頁中說明該Dynamic Faces標籤庫。 對於符合標準的非XML文法的JavaServer Pages(JSP)網頁而言,這種說明如下所示:

<%@ taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions/dynafaces" %>

  對於符合XML文法的JavaServer Pages(JSP)網頁而言,這種說明如下所示:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"
xmlns:jsfExt="http://java.sun.com/jsf/extensions/dynafaces"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">

  如果使用Facelets而非JSP,文法與JSP XML的文法非常相似,如下所示:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:jsfExt="http://java.sun.com/jsf/extensions/dynafaces"
xmlns:f="http://java.sun.com/jsf/core">

  好了。我們可以開始利用Dynamic Faces嚮應用軟體中增添Ajax功能了。

  作為一種手動設定應用軟體的替代性方案,我們可以使用Dynamic Faces下載包,其中包括面向JSP和Facelets的空白應用軟體。如果使用現成的空白應用軟體,所有的設定工作已經預先完成,我們就可以開始編寫網頁了。

利用ajaxZone標籤更新部分網頁

  確定網頁上哪些組件將支援Ajax的一種方式是用Dynamic Faces提供的ajaxZone定製標籤封裝它們。當這樣做時,我們就告訴Dynamic Faces只非同步更新使用ajaxZone標籤確定的組件樹部分。

  例如,假設我們有一個帶有一系列按鈕的網頁,客戶在網上購買汽車時,可以用這些按鈕選擇標準或豪華裝修。當客戶點擊一個按鈕時,一系列其它組件的值會發生變化,而不會造成整個網頁被更新。當客戶改變一個組件的值時,汽車的價格也會改變,但不會造成整個網頁的更新。

  圖1顯示的是cardemo應用軟體中網頁的一個螢幕快照,它使客戶能夠選擇汽車的配置情況。


圖1:選擇汽車的配置

  圖1顯示了二個由ajaxZone標籤劃分的地區。 當客戶點擊地區2中的一個按鈕時,該地區中組件的值會發生變化。當客戶改變地區2中的一個組件的值時,地區1中Your Price輸出組件的值也會隨之變化。

  要實現這樣的功能,我們需要將所有組件封裝在ajaxZone標籤中,如下所示:

<jsfExt:ajaxZone id="zone1">
<h:panelGrid columns="2">
<h:outputText styleClass="subtitle"
value="#{bundle.basePriceLabel}"/>
<h:outputText
binding="#{carstore.currentModel.components.basePrice}"/>
<h:outputText styleClass="subtitle"
value="#{bundle.yourPriceLabel}"/>
<h:outputText value="#{carstore.currentModel.currentPrice}"/>
</h:panelGrid>
</jsfExt:ajaxZone>
<jsfExt:ajaxZone id="zone2"
action="#{carstore.currentModel.updatePricing}">
<h:commandButton id="Standard" value="#{bundle.Standard}"
styleClass="#{carstore.customizers.Standard.buttonStyle}"
actionListener="#{carstore.choosePackage}"/>
<h:commandButton id="Deluxe" value="#{bundle.Deluxe}"
styleClass="#{carstore.customizers.Deluxe.buttonStyle}"
actionListener="#{carstore.choosePackage}"/>
<h:outputText value="#{bundle.Engine}"
styleClass="optionLabel"/>
<h:selectOneMenu styleClass="optionValue"
binding="#{carstore.currentModel.components.engine}"/>
<h:outputText value="#{bundle.Speakers}"
styleClass="optionLabel"/>
<h:selectOneRadio styleClass="optionValue"
binding="#{carstore.currentModel.components.speaker}"/>
</jsfExt:ajaxZone>

  前面的代碼中包含名字分別為zone1和zone2的二個域。象代碼顯示的那樣,zone 1中只有一個輸出組件,因此它不會產生任何Ajax請求; Zone 2域中包含有輸入和輸出組件。當客戶點擊2個按鈕中的1個,或者選擇菜單或選項按鈕列表中的一個選項時,zone2中的組件會啟動一個Ajax請求。這一請求將引起方法運算式#{carstore.currentModel.updatePricing}中定義的操作被調用。

  當使用域時,每個Ajax事務將使得網頁中的所有域被更新。前面例子的效果是,當使用者選擇zone 2中的任何輸入組件時,Ajax功能會自動地更新zone 1中的汽車價格資料。

  值得指出的是,我們無需編寫一行JavaScript代碼就能夠實現這一例子,我們也無需任何定製組件。這一應用軟體使用了我們熟知的普通而簡單的JavaServer Faces組件,但它們已經能夠支援Ajax功能了。

  ajaxZone標籤向網頁創作者提供了一種使用Dynamic Faces的簡單、熟悉、直觀的方式。在最簡單的例子中,ajaxZone標籤能夠向網頁創作者提供所需要的功能。ajaxZone標籤支援許多使我們能夠進一步定製其操作的其它屬性,ajaxZone文檔中包含有其屬性的完整清單。

  下面的部分將討論使用Dynamic Faces的另一種方法,它使我們能夠細粒度地控制網頁中組件的Ajax化。
使用Dynamic Faces fireAjaxTransaction方法

  為了對與Ajax相關的任務進行細粒度的控制,我們可以使用Dynamic Faces提供的內建JavaScript庫。通過使用現有組件標籤中合適的DynaFaces.fireAjaxTransaction JavaScript函數,我們可以對網頁中組件非同步更新方式有更細粒度的組件級控制。

  例如,假設我們希望網頁中的一些組件對一種類型的JavaScript事件━━例如onclick作出響應,並希望該網頁中的其它組件對其它類型的JavaScript事件作出響應。又假設我們希望產生一個Ajax請求的每個組件能夠引起組件樹的不同部分被非同步更新。為了完成這些任務,我們需要使用fireAjaxTransaction函數。

  為了使用fireAjaxTransaction函數,需要完成下面的準備工作:

  ·在一個組件標籤中增添一個JavaScript事件屬性,例如onclick。

  ·將該屬性的值設定成DynaFaces.fireAjaxTransaction函數。

  ·向該函數傳遞一系列參數。

  下面的代碼是一個簡單的Hello World例子中一個網頁的一部分,使用者可以輸入他或她的名字,點擊一個按鈕,應用程式會用一條包含使用者名稱字的問候語響應使用者的輸入。

...
<f:view>
...
<h:form id="form" prependId="false">
...
<h:graphicImage value="wave.med.gif"/>
<p>
Hello, my name is Duke. What is your name?
<p>
<h:inputText id="input" value="#{testBean.name}"/>
<h:commandButton id="button"
actionListener="#{testBean.changeText}"
onclick="DynaFaces.fireAjaxTransaction(this,
{execute: 'input', 'button',
render: 'input', 'text'}); return false;"
value="click"/>
<p>
<h:outputText id="text" value="#{testBean.text}"/>
</h:form>
...
</f:view>

  在上面的例子中,inputText標籤代表一個輸入欄位。當使用者在該輸入欄位中輸入內容,並點擊commandButton標籤表示的按鈕,就會出現下面的情況:

  1、DynaFaces.fireAjaxTransaction函數執行,使得Dynamic Faces向伺服器發送一個Ajax請求。

  2、伺服器返回一個Dynamic Faces JavaScript庫處理的特別XML響應。

  3、合適的庫函數用新的值更新HTML DOM樹。

  為了告訴fireAjaxTransaction函數如何產生Ajax請求,我們向它傳輸一系列參數。在上面的例子中,我們向fireAjaxTransaction函數傳遞了2個參數。下面是調用fireAjaxTransaction函數的代碼:

onclick="DynaFaces.fireAjaxTransaction(this,
{execute: 'input', 'button',
render: 'input', 'text'}); return false;"

  This參數指的是代表觸發該事件的按鈕的標籤,其它參數由指示Dynamic Faces如何處理該請求的選項組成。在這個例子中,選項是execute和render。

  Execute和render選項指的是JavaServer Faces生命週期的部分,2所示:


圖2: Dynamic Faces如何利用execute和render選項劃分JavaServer Faces技術的生命週期

  Execute是在postback期間執行的生命週期部分。它包含有處理模式對象的資料轉換、驗證、更新階段; Render根據對網頁的請求顯示該網頁。

  在對fireAjaxTransaction函數的調用中使用的execute選項列出了在JavaServer Faces生命週期的execute部分期間必須處理的組件的ID,Hello World例子中的這行代碼如下所示。

execute: 'input', 'button'

  接受使用者名稱的input組件必須執行生命週期的execute部分,因為它的資料必須被儲存到模式對象中。Button組件也應當執行生命週期的execute部分,因為Invoke Application階段是生命週期execute片斷的一部分。

  當生命週期的render片斷顯示一個使用Dynamic Faces的網頁時,作為一次Ajax請求的結果,它只顯示該網頁上被選定的組件。我們使用render選項顯示要重新顯示的組件的ID,Hello World例子中的render選項如下所示:

render: 'input', 'text'

  在這一例子中,作為Ajax請求的結果,生命週期的render片斷會重新顯示網頁上的input和text組件。當使用者點擊該按鈕時,代表input組件的輸入欄位和代表text組件的輸出文本會被再次顯示。輸入欄位會被重新顯示,清除在點擊該按鈕前使用者輸入的值。輸出文本會被重新顯示,顯示包含在點擊該按鈕前使用者在輸入欄位中輸入的值的資訊。該網頁上的其它組件無需被重新顯示。

  除了execute和 render選項外,我們還可以使用其它選項,進一步定製Dynamic Faces處理事件的方式。需要記住的是,使用fireAjaxTransaction函數使我們能夠對網頁中的哪些組件會得益於Ajax有更多的控制。事實上,fireAjaxTransaction函數讓我們能夠能夠使網頁中的任何組件支援Ajax,而無需編寫JavaScript或任何其它代碼。

聯合使用Dynamic Faces和jMaki

  至此,我們已經學習了如何使用Dynamic Faces重新顯示支援Ajax的JavaServer Faces組件。但是,如何增添曾經在基於JavaServer Faces的應用軟體中看到的支援Ajax的widget呢?

  我們可以利用Project jMaki將喜歡的widget封裝在JavaServer Faces組件中。這樣,我們既能夠享受到JavaServer Faces組件模式的好處,也能夠獲得使用被封裝為JavaServer Faces組件的widget的靈活性。 同時,我們無須編寫為現有組件實現Ajax功能的JavaScript代碼,以及為widget建立JavaServer Faces組件所要求的Java平台代碼。

  如何聯合使用jMaki和Dynamic Faces呢?對於網頁創作者而言,這非常簡單,就是將與jMaki widget相關的標籤拖到網頁中。
為了聯合使用jMaki widget和Dynamic Faces,widget開發人員需要對jMaki widget的組件檔案作一些小小的修改。這些修改使jMaki widget能夠充分利用JavaServer Faces技術提供的組件狀態管理系統,正確地轉換Dynamic Faces要求的header。修改的細節超出了三篇文章的討論範圍,讀者可以參閱相關資料。

  Dynamic FacesTeam Dev已經完成了轉換3個與Dynamic Faces.聯合使用的jMaki widget所需要的工作。被轉換的jMaki widget是script.aculo.us in-place editor widget、Dojo fisheye widget、Dojo inline-editor widget。

  除了轉換fisheye widget,Team Dev還修改了jMaki API,使widget能夠觸發一個JavaServer Faces價值修改事件,如所示:

<a:ajax name="dojo.fisheye"
value="#{fishEyeBean.selectedIndex}"
valueChangeListener="#{fishEyeBean.valueChanged}"
args="{items:[
{iconSrc:'images/150x126_jalopy.jpg',caption:'Jalopy',index:0},
{iconSrc:'images/150x126_luxury.jpg',caption:'Luxury',index:1},
{iconSrc:'images/150x126_roadster.jpg',caption:'Roadster',index:2},
{iconSrc:'images/150x126_suv.jpg',caption:'SUV',index:3}
]}"
/>

  Dynamic Faces和jMakiTeam Dev正在加緊工作,確保所有的jMaki widgets支援Dynamic Faces。

  現在,讓我們來站在網頁創作者的角度來討論這一問題。要想搞明白如何聯合使用jMaki script.aculo.us in-place editor widget和 Dynamic Faces,我們在一個JavaServer Faces資料表組件中包含該widget,使我們能夠編輯該表中一個單元的值。

  在JSP網頁中,我們必須說明要求的標籤庫,以及Dynamic Faces和jMaki標籤,如下所示:

<%@taglib prefix="f"
uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h"
uri="http://java.sun.com/jsf/html"%>
<%@taglib prefix="jsfExt"
uri="http://java.sun.com/jsf/extensions/dynafaces"%>
<%@taglib prefix="a"
uri="http://java.sun.com/jmaki-jsf" %>

  下面的代碼添加的是<jsfExt:scripts />標籤:

<f:view>

<html>
<head>
<title>Table with jMaki</title>
<jsfExt:scripts />
</head>
<body>

  這一標籤顯示Dynamic Faces所要求的JavaScript檔案的<script>元素。

  最後,通過包含一個指定被封裝為jMaki widget 的in-place editor的 jMaki ajax標籤,我們就將該widget添加到了網頁上。

<h:form>

<h:dataTable
...
rows="10" binding="#{ResultSetBean.data}"
value="#{ResultSetBean.list}"
var="customer">
<h:column>
<f:facet name="header">
<h:outputText value="Account Id"/>
</f:facet>
<h:outputText id="accountId"
value="#{customer.accountId}"/>
</h:column>

<h:column>
<f:facet name="header">
<h:outputText value="Customer Name"/>
</f:facet>
<a:ajax name="scriptaculous.inplace"
value="#{customer.name}"/>
</h:column>
</h:dataTable>
...

</h:form>
</body>
</html>
</f:view>

  圖3顯示的是上述網頁:


圖3:使用者修改一個單元的值之前

  圖4顯示的是當使用者點擊Customer Name列中一個單元的連結時的情況:


圖4: 使用者點擊Customer Name列中一個連結後的情況

  需要注意的是,當使用者點擊Customer Name列中的一個元素時,客戶名字元素會被一個輸入組件、一個"OK"按鈕、一個"Cancel"連結所取代,使使用者能夠編輯當前的客戶名字。如果使用者點擊"Cancel"而不是"OK",該單元就會被重新顯示為原來的值;如果使用者輸入一個值,並點擊"OK"按鈕,新的值就會被利用Ajax技術發送到伺服器,使該模式更新為新的值。 然後,被編輯的單元就會被重新顯示。 圖5顯示的是是單元被修改後的網頁:


圖5:在使用者向伺服器提交新的值後,網頁重新顯示為新的值

  結論

  Project Dynamic Faces向我們提供了一種向基於JavaServer Faces的應用軟體中添加Ajax功能的靈活、有效方式,而無需放棄JavaServer Faces組件模式的任何優勢。在內建的JavaScript庫、Ajax實現、Dynamic Faces提供的組件互動模式的協助下,我們會發現利用Dynamic Faces添加Ajax功能更容易了。基於JavaServer Faces的應用軟體能夠得益於jMaki widget提供的更多的靈活性。

 

本文轉自: http://hi.baidu.com/shker/blog/item/a87a45da48a2a8dab7fd484d.html

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.