




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
面向Java程序員的AJAX面向Java程序員的AJAX面向Java程序員的AJAX面向Java程序員的AJAX編制僅供參考審核批準(zhǔn)生效日期地址:電話:傳真:郵編:面向
Java開(kāi)發(fā)人員的Ajax:
構(gòu)建動(dòng)態(tài)的Java應(yīng)用程序Ajax為更好的Web應(yīng)用程序鋪平了道路打印本頁(yè)將此頁(yè)作為電子郵件發(fā)送討論樣例代碼級(jí)別:中級(jí)PhilipMcCarthy
(C:\Users\Administrator\Desktop\封面(2)\subject=構(gòu)建動(dòng)態(tài)的Java應(yīng)用程序),軟件開(kāi)發(fā)顧問(wèn),獨(dú)立咨詢顧問(wèn)2005年10月20日在Web應(yīng)用程序開(kāi)發(fā)中,頁(yè)面重載循環(huán)是最大的一個(gè)使用障礙,對(duì)于Java?開(kāi)發(fā)人員來(lái)說(shuō)也是一個(gè)嚴(yán)峻的挑戰(zhàn)。在這個(gè)系列中,作者PhilipMcCarthy介紹了一種創(chuàng)建動(dòng)態(tài)應(yīng)用程序體驗(yàn)的開(kāi)創(chuàng)性方式。Ajax(異步JavaScript和XML)是一種編程技術(shù),它允許為基于Java的Web應(yīng)用程序把Java技術(shù)、XML和JavaScript組合起來(lái),從而打破頁(yè)面重載的范式。Ajax(即異步JavaScript和XML)是一種Web應(yīng)用程序開(kāi)發(fā)的手段,它采用客戶端腳本與Web服務(wù)器交換數(shù)據(jù)。所以,不必采用會(huì)中斷交互的完整頁(yè)面刷新,就可以動(dòng)態(tài)地更新Web頁(yè)面。使用Ajax,可以創(chuàng)建更加豐富、更加動(dòng)態(tài)的Web應(yīng)用程序用戶界面,其即時(shí)性與可用性甚至能夠接近本機(jī)桌面應(yīng)用程序。Ajax不是一項(xiàng)技術(shù),而更像是一個(gè)
模式
——一種識(shí)別和描述有用的設(shè)計(jì)技術(shù)的方式。Ajax是新穎的,因?yàn)樵S多開(kāi)發(fā)人員才剛剛開(kāi)始知道它,但是所有實(shí)現(xiàn)Ajax應(yīng)用程序的組件都已經(jīng)存在若干年了。它目前受到重視是因?yàn)樵?004和2005年出現(xiàn)了一些基于Ajax技術(shù)的非常棒的動(dòng)態(tài)WebUI,最著名的就是Google的GMail和Maps應(yīng)用程序,以及照片共享站點(diǎn)Flickr。這些用戶界面具有足夠的開(kāi)創(chuàng)性,有些開(kāi)發(fā)人員稱之為“Web”,因此對(duì)Ajax應(yīng)用程序的興趣飛速上升。在這個(gè)系列中,我將提供使用Ajax開(kāi)發(fā)應(yīng)用程序需要的全部工具。在第一篇文章中,我將解釋Ajax背后的概念,演示為基于Java的Web應(yīng)用程序創(chuàng)建Ajax界面的基本步驟。我將使用代碼示例演示讓Ajax應(yīng)用程序如此動(dòng)態(tài)的服務(wù)器端Java代碼和客戶端JavaScript。最后,我將指出Ajax方式的一些不足,以及在創(chuàng)建Ajax應(yīng)用程序時(shí)應(yīng)當(dāng)考慮的一些更廣的可用性和訪問(wèn)性問(wèn)題。更好的購(gòu)物車(chē)可以用Ajax增強(qiáng)傳統(tǒng)的Web應(yīng)用程序,通過(guò)消除頁(yè)面裝入從而簡(jiǎn)化交互。為了演示這一點(diǎn),我采用一個(gè)簡(jiǎn)單的購(gòu)物車(chē)示例,在向里面添加項(xiàng)目時(shí),它會(huì)動(dòng)態(tài)更新。這項(xiàng)技術(shù)如果整合到在線商店,那么用戶可以持續(xù)地瀏覽和向購(gòu)物車(chē)中添加項(xiàng)目,而不必在每次點(diǎn)擊之后都等候完整的頁(yè)面更新。雖然這篇文章中的有些代碼特定于購(gòu)物車(chē)示例,但是演示的技術(shù)可以應(yīng)用于任何Ajax應(yīng)用程序。清單1顯示了購(gòu)物車(chē)示例使用的有關(guān)HTML代碼,整篇文章中都會(huì)使用這個(gè)HTML。
清單1.購(gòu)物車(chē)示例的有關(guān)片斷<!--Tableofproductsfromstore'scatalog,onerowperitem--><th>Name</th><th>Description</th><th>Price</th><th></th>...<tr><!--Itemdetails--><td>Hat</td><td>Stylishbowlerhat</td><td>$</td><td><!--ClickbuttontoadditemtocartviaAjaxrequest--><buttononclick="addToCart('hat001')">AddtoCart</button></td></tr>...<!--Representationofshoppingcart,updatedasynchronously--><ulid="cart-contents"><!--List-itemswillbeaddedhereforeachiteminthecart--></ul><!--Totalcostofitemsincartdisplayedinsidespanelement-->Totalcost:<spanid="total">$</span>
回頁(yè)首Ajax往返過(guò)程Ajax交互開(kāi)始于叫作
XMLHttpRequest
的JavaScript對(duì)象。顧名思義,它允許客戶端腳本執(zhí)行HTTP請(qǐng)求,并解析XML服務(wù)器響應(yīng)。Ajax往返過(guò)程的第一步是創(chuàng)建
XMLHttpRequest
的實(shí)例。在XMLHttpRequest
對(duì)象上設(shè)置請(qǐng)求使用的HTTP方法(GET
或
POST)以及目標(biāo)URL?,F(xiàn)在,您還記得Ajax的第一個(gè)
a
是代表
異步(asynchronous)
嗎在發(fā)送HTTP請(qǐng)求時(shí),不想讓瀏覽器掛著等候服務(wù)器響應(yīng)。相反,您想讓瀏覽器繼續(xù)對(duì)用戶與頁(yè)面的交互進(jìn)行響應(yīng),并在服務(wù)器響應(yīng)到達(dá)時(shí)再進(jìn)行處理。為了實(shí)現(xiàn)這個(gè)要求,可以在
XMLHttpRequest
上注冊(cè)一個(gè)回調(diào)函數(shù),然后異步地分派
XMLHttpRequest。然后控制就會(huì)返回瀏覽器,當(dāng)服務(wù)器響應(yīng)到達(dá)時(shí),會(huì)調(diào)用回調(diào)函數(shù)。在JavaWeb服務(wù)器上,請(qǐng)求同其他
HttpServletRequest
一樣到達(dá)。在解析了請(qǐng)求參數(shù)之后,servlet調(diào)用必要的應(yīng)用程序邏輯,把響應(yīng)序列化成XML,并把XML寫(xiě)入
HttpServletResponse?;氐娇蛻舳藭r(shí),現(xiàn)在調(diào)用注冊(cè)在
XMLHttpRequest
上的回調(diào)函數(shù),處理服務(wù)器返回的XML文檔。最后,根據(jù)服務(wù)器返回的數(shù)據(jù),用JavaScript操縱頁(yè)面的HTMLDOM,把用戶界面更新。圖1是Ajax往返過(guò)程的順序圖。
圖1.Ajax往返過(guò)程
現(xiàn)在您對(duì)Ajax往返過(guò)程有了一個(gè)高層面的認(rèn)識(shí)。下面我將放大其中的每一步驟,進(jìn)行更詳細(xì)的觀察。如果過(guò)程中迷了路,請(qǐng)回頭看圖1——由于Ajax方式的異步性質(zhì),所以順序并非十分簡(jiǎn)單。
回頁(yè)首分派XMLHttpRequest我將從Ajax序列的起點(diǎn)開(kāi)始:創(chuàng)建和分派來(lái)自瀏覽器的
XMLHttpRequest。不幸的是,不同的瀏覽器創(chuàng)建
XMLHttpRequest
的方法各不相同。清單2的JavaScript函數(shù)消除了這些依賴于瀏覽器的技巧,它可以檢測(cè)當(dāng)前瀏覽器要使用的正確方式,并返回一個(gè)可以使用的
XMLHttpRequest。最好是把它當(dāng)作輔助代碼:只要把它拷貝到JavaScript庫(kù),并在需要
XMLHttpRequest
的時(shí)候使用它就可以了。
清單2.創(chuàng)建跨瀏覽器的XMLHttpRequest/**ReturnsanewXMLHttpRequestobject,orfalseifthisbrowser*doesn'tsupportit*/functionnewXMLHttpRequest(){varxmlreq=false;if{分派AddtoCartXMLHttpRequest/**Addsanitem,identifiedbyitsproductcode,totheshoppingcart*itemCode-productcodeoftheitemtoadd.*/functionaddToCart(itemCode){("POST","",true);("action=add&item="+itemCode);}這就是建立Ajax往返過(guò)程的第一部分,即創(chuàng)建和分派來(lái)自客戶機(jī)的HTTP請(qǐng)求。接下來(lái)是用來(lái)處理請(qǐng)求的Javaservlet代碼。
回頁(yè)首servlet請(qǐng)求處理用servlet處理
XMLHttpRequest,與處理普通的瀏覽器HTTP請(qǐng)求一樣。可以用
()
得到在POST請(qǐng)求體中發(fā)送的表單編碼數(shù)據(jù)。Ajax請(qǐng)求被放進(jìn)與來(lái)自應(yīng)用程序的常規(guī)Web請(qǐng)求一樣的
HttpSession
中。對(duì)于示例購(gòu)物車(chē)場(chǎng)景來(lái)說(shuō),這很有用,因?yàn)檫@讓我可以把購(gòu)物車(chē)狀態(tài)封裝在JavaBean中,并在請(qǐng)求之間在會(huì)話中維持這個(gè)狀態(tài)。清單4是處理Ajax請(qǐng)求、更新購(gòu)物車(chē)的簡(jiǎn)單servlet的一部分。Cart
bean是從用戶會(huì)話中獲得的,并根據(jù)請(qǐng)求參數(shù)更新它的狀態(tài)。然后
Cart
被序列化成XML,XML又被寫(xiě)入
ServletResponse。重要的是把響應(yīng)的內(nèi)容類(lèi)型設(shè)置為
application/xml,否則
XMLHttpRequest
不會(huì)把響應(yīng)內(nèi)容解析成XMLDOM。
清單4.處理Ajax請(qǐng)求的servlet代碼publicvoiddoPost(HttpServletRequestreq,HttpServletResponseres)throws{Cartcart=getCartFromSession(req);Stringaction=("action");Stringitem=("item");if((action!=null)&&(item!=null)){quals(action)){(item);}elseif("remove".equals(action)){(item);}}("application/xml");().write(cartXml);}清單5顯示了
()
方法生成的示例XML。它很簡(jiǎn)單。請(qǐng)注意
cart
元素的
generated
屬性,它是
()
生成的一個(gè)時(shí)間戳。
清單5.Cart對(duì)象的XML序列化示例
<xmlversion=""><cartgenerated=""total="$"><itemcode="hat001"><name>Hat</name><quantity>2</quantity></item><itemcode="cha001"><name>Chair</name><quantity>1</quantity></item><itemcode="dog001"><name>Dog</name><quantity>1</quantity></item></cart>如果查看應(yīng)用程序源代碼(可以從
下載
一節(jié)得到)中的,可以看到生成XML的方式只是把字符串添加在一起。雖然對(duì)這個(gè)示例來(lái)說(shuō)足夠了,但是對(duì)于從Java代碼生成XML來(lái)說(shuō)則是最差的方式。我將在這個(gè)系列的下一期中介紹一些更好的方式?,F(xiàn)在您已經(jīng)知道了
CartServlet
響應(yīng)
XMLHttpRequest
的方式。下一件事就是返回客戶端,查看如何用XML響應(yīng)更新頁(yè)面狀態(tài)。
回頁(yè)首用JavaScript進(jìn)行響應(yīng)處理XMLHttpRequest
的
readyState
屬性是一個(gè)數(shù)值,它指出請(qǐng)求生命周期的狀態(tài)。它從0(代表“未初始化”)變化到4(代表“完成”)。每次
readyState
變化時(shí),readystatechange
事件就觸發(fā),由onreadystatechange
屬性指定的事件處理函數(shù)就被調(diào)用。在
清單3
中已經(jīng)看到了如何調(diào)用
getReadyStateHandler()
函數(shù)創(chuàng)建事件處理函數(shù)。然后把這個(gè)事件處理函數(shù)分配給
onreadystatechange
屬性。getReadyStateHandler()
利用了這樣一個(gè)事實(shí):函數(shù)是JavaScript中的一級(jí)對(duì)象。這意味著函數(shù)可以是其他函數(shù)的參數(shù),也可以創(chuàng)建和返回其他函數(shù)。getReadyStateHandler()
的工作是返回一個(gè)函數(shù),檢查
XMLHttpRequest
是否已經(jīng)完成,并把XML響應(yīng)傳遞給調(diào)用者指定的事件處理函數(shù)。清單6是
getReadyStateHandler()
的代碼。
清單6.getReadyStateHandler()函數(shù)/**ReturnsafunctionthatwaitsforthespecifiedXMLHttpRequest*tocomplete,thenpassesitsXMLresponsetothegivenhandlerfunction.*req-TheXMLHttpRequestwhosestateischanging*responseXmlHandler-FunctiontopasstheXMLresponseto*/functiongetReadyStateHandler(req,responseXmlHandler){更新頁(yè)面,反映購(gòu)物車(chē)的XML文檔functionupdateCart(cartXML){varquantity=("quantity")[0].;nnerHTML=("total");}到此,整個(gè)Ajax往返過(guò)程完成了,但是您可能想讓W(xué)eb應(yīng)用程序運(yùn)行一下查看實(shí)際效果(請(qǐng)參閱
下載
一節(jié))。這個(gè)示例非常簡(jiǎn)單,有很多需要改進(jìn)之處。例如,我包含了從購(gòu)物車(chē)中清除項(xiàng)目的服務(wù)器端代碼,但是無(wú)法從UI訪問(wèn)它。作為一個(gè)好的練習(xí),請(qǐng)?jiān)囍趹?yīng)用程序現(xiàn)有的JavaScript代碼之上構(gòu)建出能夠?qū)崿F(xiàn)這個(gè)功能的代碼。
回頁(yè)首使用Ajax的挑戰(zhàn)就像任何技術(shù)一樣,使用Ajax也有許多出錯(cuò)的可能性。我目前在這里討論的問(wèn)題還缺乏容易的解決方案,但是會(huì)隨著Ajax的成熟而改進(jìn)。隨著開(kāi)發(fā)人員社區(qū)增加開(kāi)發(fā)Ajax應(yīng)用程序的經(jīng)驗(yàn),將會(huì)記錄下最佳實(shí)踐和指南。XMLHttpRequest的可用性Ajax開(kāi)發(fā)人員面臨的一個(gè)最大問(wèn)題是:在沒(méi)有
XMLHttpRequest
可用時(shí)該如何響應(yīng)雖然主要的現(xiàn)代瀏覽器都支持
XMLHttpRequest,但仍然有少數(shù)用戶的瀏覽器不支持,或者瀏覽器的安全設(shè)置阻止使用XMLHttpRequest。如果開(kāi)發(fā)的Web應(yīng)用程序要部署在企業(yè)內(nèi)部網(wǎng),那么可能擁有指定支持哪種瀏覽器的權(quán)力,從而可以認(rèn)為
XMLHttpRequest
總能使用。但是,如果要部署在公共Web上,那么就必須當(dāng)心,如果假設(shè)
XMLHttpRequest
可用,那么就可能會(huì)阻止那些使用舊的瀏覽器、殘疾人專(zhuān)用瀏覽器和手持設(shè)備上的輕量級(jí)瀏覽器的用戶使用您的應(yīng)用程序。所以,您應(yīng)當(dāng)努力讓?xiě)?yīng)用程序“平穩(wěn)降級(jí)”,在沒(méi)有
XMLHttpRequest
支持的瀏覽器中也能夠工作。在購(gòu)物車(chē)的示例中,把應(yīng)用程序降級(jí)的最好方式可能是讓AddtoCart按鈕執(zhí)行一個(gè)常規(guī)的表單提交,刷新頁(yè)面來(lái)反映購(gòu)物車(chē)更新后的狀態(tài)。Ajax的行為應(yīng)當(dāng)在頁(yè)面裝入的時(shí)候就通過(guò)JavaScript添加到頁(yè)面,只有在
XMLHttpRequest
可用時(shí)才把JavaScript事件處理函數(shù)附加到每個(gè)AddtoCart按鈕。另一種方式是在用戶登錄時(shí)檢測(cè)
XMLHttpRequest
是否可用,然后相應(yīng)地提供應(yīng)用程序的Ajax版本或基于表單的普通版本??捎眯钥紤]關(guān)于Ajax應(yīng)用程序的某些可用性問(wèn)題比較普遍。例如,讓用戶知道他們的輸入已經(jīng)注冊(cè)了可能是重要的,因?yàn)樯陈┕鈽?biāo)和spinning瀏覽器的常用反饋機(jī)制“throbber”對(duì)
XMLHttpRequest
不適用。一種技術(shù)是用“Nowupdating...”類(lèi)型的信息替換Submit按鈕,這樣用戶在等候響應(yīng)期間就不會(huì)反復(fù)單擊按鈕了。另一個(gè)問(wèn)題是,用戶可能沒(méi)有注意到他們正在查看的頁(yè)面的某一部分已經(jīng)更新了。可以使用不同的可視技術(shù),把用戶的眼球帶到頁(yè)面的更新區(qū)域,從而緩解這個(gè)問(wèn)題。由Ajax更新頁(yè)面造成的其他問(wèn)題還包括:“破壞了”瀏覽器的后退按鈕,地址欄中的URL也無(wú)法反映頁(yè)面的整個(gè)狀態(tài),妨礙了設(shè)置書(shū)簽。請(qǐng)參閱
參考資料
一節(jié),獲得專(zhuān)門(mén)解決Ajax應(yīng)用程序可用性問(wèn)題的文章。服務(wù)器負(fù)載用Ajax實(shí)現(xiàn)代替普通的基于表單的UI,會(huì)大大提高對(duì)服務(wù)器發(fā)出的請(qǐng)求數(shù)量。例如,一個(gè)普通的GoogleWeb搜索對(duì)服務(wù)器只有一個(gè)請(qǐng)求,是在用戶提交搜索表單時(shí)出現(xiàn)的。而GoogleSuggest試圖自動(dòng)完成搜索術(shù)語(yǔ),它要在用戶輸入時(shí)向服務(wù)器發(fā)送多個(gè)請(qǐng)求。在開(kāi)發(fā)Ajax應(yīng)用程序時(shí),要注意將要發(fā)送給服務(wù)器的請(qǐng)求數(shù)量以及由此造成的服務(wù)器負(fù)荷。降低服務(wù)器負(fù)載的辦法是,在客戶機(jī)上對(duì)請(qǐng)求進(jìn)行緩沖并且緩存服務(wù)器響應(yīng)(如果可能的話)。還應(yīng)該嘗試將AjaxWeb應(yīng)用程序設(shè)計(jì)為在客戶機(jī)上執(zhí)行盡可能多的邏輯,而不必聯(lián)絡(luò)服務(wù)器。處理異步非常重要的是,要理解無(wú)法保證
XMLHttpRequest
會(huì)按照分派它們的順序完成。實(shí)際上,應(yīng)當(dāng)假設(shè)它們不會(huì)按順序完成,并且在設(shè)計(jì)應(yīng)用程序時(shí)把這一點(diǎn)記在心上。在購(gòu)物車(chē)的示例中,使用最后更新的時(shí)間戳來(lái)確保新的購(gòu)物車(chē)數(shù)據(jù)不會(huì)被舊的數(shù)據(jù)覆蓋(請(qǐng)參閱
清單7)。這個(gè)非?;镜姆绞娇梢杂糜谫?gòu)物車(chē)場(chǎng)景,但是可能不適合其他場(chǎng)景。所以在設(shè)計(jì)時(shí)請(qǐng)考慮如何處理異步的服務(wù)器響應(yīng)。
回頁(yè)首結(jié)束語(yǔ)現(xiàn)在您對(duì)Ajax的基本原則應(yīng)當(dāng)有了很好的理解,對(duì)參與Ajax交互的客戶端和服務(wù)器端組件也應(yīng)當(dāng)有了初步的知識(shí)。這些是基于Java的AjaxWeb應(yīng)用程序的構(gòu)造塊。另外,您應(yīng)當(dāng)理解了伴隨Ajax方式的一些高級(jí)設(shè)計(jì)問(wèn)題。創(chuàng)建成功的Ajax應(yīng)用程序要求整體考慮,從UI設(shè)計(jì)到JavaScript設(shè)計(jì),再到服務(wù)器端架構(gòu);但是您現(xiàn)在應(yīng)當(dāng)已經(jīng)武裝了考慮其他這些方面所需要的核心Ajax知識(shí)。如果使用這里演示的技術(shù)編寫(xiě)大型Ajax應(yīng)用程序的復(fù)雜性讓您覺(jué)得恐慌,那么有好消息給您。由于Struts、Spring和Hibernate這類(lèi)框架的發(fā)展把Web應(yīng)用程序開(kāi)發(fā)從底層ServletAPI和JDBC的細(xì)節(jié)中抽象出來(lái),所以正在出現(xiàn)簡(jiǎn)化Ajax開(kāi)發(fā)的工具包。其中有些只側(cè)重于客戶端,提供了向頁(yè)面添加可視效果的簡(jiǎn)便方式,或者簡(jiǎn)化了對(duì)
XMLHttpRequest
的使用。有些則走得更遠(yuǎn),提供了從服務(wù)器端代碼自動(dòng)生成Ajax接口的方式。這些框架替您完成了繁重的任務(wù),所以您可以采用更高級(jí)的方式進(jìn)行Ajax開(kāi)發(fā)。我在這個(gè)系列中將研究其中的一些。Ajax社區(qū)正在快速前進(jìn),所以會(huì)有大量有價(jià)值的信息涌現(xiàn)。在閱讀這個(gè)系列的下一期之前,我建議您參考
參考資料
一節(jié)中列出的文章,特別是如果您是剛接觸Ajax或客戶端開(kāi)發(fā)的話。您還應(yīng)當(dāng)花些時(shí)間研究示例源代碼并考慮一些增強(qiáng)它的方式。在這個(gè)系列的下一篇文章中,我將深入討論
XMLHttpRequest
API,并推薦一些從JavaBean方便地創(chuàng)建XML的方式。我還將介紹替代XML進(jìn)行Ajax數(shù)據(jù)傳遞的方式,例如JSON(JavaScriptObjectNotation)輕量級(jí)數(shù)據(jù)交換格式。
回頁(yè)首下載描述名字大小下載方法Samplecode8KBHTTP關(guān)于下載方法的信息參考資料學(xué)習(xí)您可以參閱本文在developerWorks全球站點(diǎn)上的
英文原文。“BeyondtheDOM”(DetheElza,developerWorks,2005年5月):進(jìn)行XML文檔訪問(wèn)的有用的JavaScript技術(shù)?!癆JAX及使用E4X編寫(xiě)Web服務(wù)腳本,第1部分”(PaulFremantle和AnthonyElder,developerWorks,2005年4月):用Ajax在支持E4XJavaScript擴(kuò)展的瀏覽器中進(jìn)行SOAP調(diào)用?!癆jax:ANewApproachtoWebApplications”(JesseJamesGarrett,AdaptivePath,2005年2月):介紹Ajax起源的短文。TheJavaBluePrintsSolutionsCatalog:介紹了Ajax在幾個(gè)常見(jiàn)Web應(yīng)用程序場(chǎng)景中的應(yīng)用。:包含多項(xiàng)改進(jìn)Ajax應(yīng)用程序的UI技術(shù)。XMLHttpRequestUsabilityGuidelines:對(duì)使用Ajax提高用戶體驗(yàn)的建議。AjaxMistakes:Ajax應(yīng)用程序應(yīng)當(dāng)避免的可用性問(wèn)題。Java技術(shù)專(zhuān)區(qū):在這里可以找到關(guān)于Java編程的各個(gè)方面的文章。
獲得產(chǎn)品和技術(shù)MozillaFirefox:DOMInspector和JavaScriptDebugger擴(kuò)展消除了許多Ajax開(kāi)發(fā)的痛苦。
討論參與論壇討論。developerWorksblogs:加入developerWorks社區(qū)。面向Java開(kāi)發(fā)人員的Ajax:
Ajax的Java對(duì)象序列化在Ajax應(yīng)用程序中序列化數(shù)據(jù)的五種途徑級(jí)別:中級(jí)PhilipMcCarthy
(C:\Users\Administrator\Desktop\封面(2)\subject=Ajax的Java對(duì)象序列化),軟件開(kāi)發(fā)顧問(wèn),獨(dú)立顧問(wèn)2005年10月24日如果您正在使用異步JavaScript和XML(Ajax)進(jìn)行Java?Web開(kāi)發(fā),那么您最關(guān)心的問(wèn)題可能就是把數(shù)據(jù)從服務(wù)器傳遞給客戶機(jī)。在
面向Java開(kāi)發(fā)人員的Ajax
系列的第二篇文章中,PhilipMcCarthy介紹了Java對(duì)象序列化的五種方式,并提供了選擇最適合應(yīng)用程序的數(shù)據(jù)格式和技術(shù)所需要的全部信息。在這個(gè)系列的
第一篇文章
中,我介紹了Ajax的構(gòu)造塊:如何用JavaScript
XMLHttpRequest
對(duì)象從Web頁(yè)面向服務(wù)器發(fā)送異步請(qǐng)求。如何用Javaservlet處理和響應(yīng)請(qǐng)求(向客戶機(jī)返回XML文檔)。如何在客戶端用響應(yīng)文檔更新頁(yè)面視圖。這一次,我將繼續(xù)討論Ajax開(kāi)發(fā)的基礎(chǔ)知識(shí),但是將側(cè)重于許多JavaWeb開(kāi)發(fā)人員最關(guān)心的問(wèn)題:為客戶機(jī)生成數(shù)據(jù)。多數(shù)Java開(kāi)發(fā)人員已經(jīng)把模型-視圖-控制器(MVC)模式應(yīng)用在他們的Web應(yīng)用程序上。在傳統(tǒng)的Web應(yīng)用程序中,視圖組件由JSP或者其他表示技術(shù)(例如Velocity模板)構(gòu)成。這些表示組件動(dòng)態(tài)地生成全新的HTML頁(yè)面,替代用戶以前正在查看的頁(yè)面,從而更新用戶界面。但是,在JavaWeb應(yīng)用程序使用AjaxUI的情況下,基于從
XMLHttpRequest
的響應(yīng)接收到的數(shù)據(jù),JavaScript客戶端代碼對(duì)于更新用戶看到的內(nèi)容負(fù)有最終責(zé)任。從服務(wù)器的角度來(lái)看,視圖成為它響應(yīng)客戶機(jī)請(qǐng)求而發(fā)送的數(shù)據(jù)表示。這篇文章側(cè)重于可以用來(lái)生成Java對(duì)象以數(shù)據(jù)為中心的視圖的技術(shù)。我將演示可以把JavaBeans變成XML文檔的各種方法,并且討論每種方法的優(yōu)劣。您將看到為什么XML并不總是最好的途徑:對(duì)于簡(jiǎn)單的Ajax請(qǐng)求來(lái)說(shuō),傳輸純文本更好。最后,我將介紹JavaScript對(duì)象標(biāo)注(JSON)。JSON允許數(shù)據(jù)以序列化的JavaScript對(duì)象圖的形式傳輸,在客戶端代碼中處理序列化的JavaScript對(duì)象圖極為容易。關(guān)于示例我將使用一個(gè)示例應(yīng)用程序和幾個(gè)用例來(lái)演示這里討論的技術(shù)特性和技術(shù)。圖1顯示的極為簡(jiǎn)單的數(shù)據(jù)模型可以表示示例用例。這個(gè)模型代表在線商店中的顧客帳戶。顧客擁有以前訂單的集合,每個(gè)訂單包含幾個(gè)商品。
圖1.簡(jiǎn)單的對(duì)象模型
雖然
XMLHttpRequest
對(duì)于發(fā)送數(shù)據(jù)使用的格式?jīng)]有做任何限制,但是對(duì)于多數(shù)目的來(lái)說(shuō),只發(fā)送傳統(tǒng)的表單數(shù)據(jù)是適合的,所以我的討論集中在服務(wù)器的響應(yīng)上。響應(yīng)也可以有基于文本的格式,但是正如它的名字表示的,XMLHttpRequest
具有內(nèi)置的處理XML響應(yīng)數(shù)據(jù)的能力。這使XML成為Ajax響應(yīng)的默認(rèn)選擇,所以我們從XML格式開(kāi)始討論。從Java類(lèi)產(chǎn)生XML把Ajax響應(yīng)作為XML來(lái)傳遞有許多原因:每個(gè)支持Ajax的瀏覽器都有導(dǎo)航XML文檔的方法,也有許多服務(wù)器端技術(shù)可以處理XML數(shù)據(jù)。通過(guò)制定一個(gè)方案,描述要交換的文檔類(lèi)型,在Ajax客戶端和服務(wù)器端之間很容易定義合約,而且如果服務(wù)器端架構(gòu)采用面向服務(wù)的方式,那么使用XML也可以允許非Ajax客戶機(jī)使用您提供的數(shù)據(jù)。我將考慮從Java對(duì)象產(chǎn)生XML數(shù)據(jù)的三種方法,并討論每種方法的優(yōu)劣。自行進(jìn)行序列化首先,可以從對(duì)象圖以編程的方式生成XML。這種方式可以簡(jiǎn)單到只是在每個(gè)JavaBean類(lèi)中實(shí)現(xiàn)
toXml()
方法即可。然后就可以選擇合適的XMLAPI,讓每個(gè)bean提供表示自己狀態(tài)的元素,并遞歸地對(duì)自己的成員調(diào)用對(duì)象圖。顯然,這種方式無(wú)法擴(kuò)展到大量的類(lèi),因?yàn)槊總€(gè)類(lèi)都需要專(zhuān)門(mén)編寫(xiě)自己的XML生成代碼。從好的方面來(lái)看,這是一個(gè)實(shí)現(xiàn)起來(lái)簡(jiǎn)單的方式,沒(méi)有額外的配置支出或者更復(fù)雜的構(gòu)建過(guò)程支出,任何JavaBean圖都可以只用幾個(gè)調(diào)用就變成XML文檔。在本系列
前一篇文章
的示例代碼中,我把XML標(biāo)記字符串連接在一起,實(shí)現(xiàn)了
toXml()
方法。上次我就提到過(guò),這是個(gè)糟糕的方法,因?yàn)樗汛_保標(biāo)記配對(duì)、實(shí)體編碼等工作的負(fù)擔(dān)放在每個(gè)
toXml()
方法的代碼中。在Java平臺(tái)上有幾個(gè)XMLAPI可以替您做這些工作,這樣您就可以把精力集中在XML的內(nèi)容上。清單1用JDOMAPI實(shí)現(xiàn)了在線商店示例中表示訂單的類(lèi)中的
toXml()(請(qǐng)參閱
圖1)。
清單1.Order類(lèi)的toXml()的JDOM實(shí)現(xiàn) publicElementtoXml(){ElementelOrder=newElement("order");("id",id);("cost",getFormattedCost());ElementelDate=newElement("date").addContent(date);(elDate);ElementelItems=newElement("items");for(Iterator<Item>iter=();();){().toXml());}(elItems);returnelOrder;}在這里可以看到用JDOM創(chuàng)建元素、使用屬性和添加元素內(nèi)容有多么簡(jiǎn)單。遞歸地調(diào)用復(fù)合JavaBean的
toXml()
方法是為了取得它們子圖的
Element
表示。例如,items
元素的內(nèi)容是通過(guò)調(diào)用
Order聚合的每個(gè)
Item
對(duì)象上的
toXml()
得到的。一旦所有的JavaBean都實(shí)現(xiàn)了
toXml()
方法,那么把任意對(duì)象圖序列化成XML文檔并返回給Ajax客戶機(jī)就簡(jiǎn)單了,如清單2所示。
清單2.從JDOM元素生成XML響應(yīng) publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres)throwsServletException{StringcustId=("username");Customercustomer=getCustomer(custId);ElementresponseElem=();DocumentresponseDoc=newDocument(responseElem);("application/xml");newXMLOutputter().output(responseDoc,());}JDOM再次把工作變得非常簡(jiǎn)單。只需要在對(duì)象圖返回的XML元素外面包裝一個(gè)
Document,然后用
XMLOutputter
把文檔寫(xiě)入servlet響應(yīng)即可。清單3顯示了用這種方式生成的XML示例,用JDOM
()
對(duì)
XMLOutputter
進(jìn)行初始化,格式化得非常好。在這個(gè)示例中,顧客只做了一個(gè)訂單,包含兩個(gè)商品。
清單3.代表顧客的XML文檔 <xmlversion=""encoding="UTF-8"><customerusername="jimmy66"><realname>JamesHyrax</realname><orders><orderid="o-11123"cost="$"><date>08-26-2005</date><items><itemid="i-55768"><name>Oolong512MBCFCard</name><description>512MegabyteType1CompactFlashcard.ManufacturedbyOolongIndustries</description><price>$</price></item><itemid="i-74491"><name>FujakSuperpix72Camera</name><description>Megapixeldigitalcamerafeaturingsixshootingmodesand3xopticalzoom.Silver.</description><price>$</price></item></items></order></orders></customer>自行序列化的不足有趣的是,清單3中的代碼展示了讓JavaBean把自己序列化為XML的一個(gè)主要不足。假設(shè)要用這個(gè)文檔表示顧客的訂單歷史視圖。在這種情況下,不太可能要顯示每個(gè)歷史訂單中每個(gè)商品的完整說(shuō)明,或者告訴顧客他或她自己的姓名。但是如果應(yīng)用程序有一個(gè)
ProductSearch
類(lèi),它就是以
Item
bean列表的形式返回搜索結(jié)果,那么在
Item
的XML表示中包含說(shuō)明可能會(huì)有幫助。而且,Item
類(lèi)上代表當(dāng)前庫(kù)存水平的額外字段,在產(chǎn)品搜索視圖中可能就是需要顯示的有用信息。但是,不管當(dāng)前的庫(kù)存水平是否與當(dāng)前情況相關(guān)(比如對(duì)顧客的訂單歷史來(lái)說(shuō)),這個(gè)字段都會(huì)從包含
Item
的任何對(duì)象圖中序列化出來(lái)。從設(shè)計(jì)的角度來(lái)看,這是數(shù)據(jù)模型與視圖生成耦合的經(jīng)典問(wèn)題。每個(gè)bean只能用一種途徑序列化自己,一成不變的方式意味著Ajax交互最終要交換它們不需要交換的數(shù)據(jù),因此造成客戶端代碼要從文檔中找到需要的信息更加困難,而且也會(huì)增加帶寬消耗和客戶端的XML解析時(shí)間。這種耦合的另一個(gè)后果就是XML的語(yǔ)法不能脫離Java類(lèi)獨(dú)立變化。例如,對(duì)顧客文檔的方案做修改,可能會(huì)影響多個(gè)Java類(lèi),造成它們也不得不做修改和重新編譯。我稍后會(huì)解決這些問(wèn)題,但是首先來(lái)看一個(gè)對(duì)自行序列化方式的可伸縮性問(wèn)題的解決方案:XML綁定框架。XML綁定框架近些年來(lái),已經(jīng)開(kāi)發(fā)了多個(gè)JavaAPI來(lái)簡(jiǎn)化XML文檔到Java對(duì)象圖的綁定過(guò)程。多數(shù)都提供了XML編排和拆解;也就是說(shuō),它們可以在Java對(duì)象圖和XML之間執(zhí)行雙向會(huì)話。這些框架封裝了XML處理的全部工作,這意味著應(yīng)用程序代碼只需要處理普通的Java類(lèi)。它們還希望提供有用的輔助功能,例如文檔驗(yàn)證。籠統(tǒng)來(lái)說(shuō),這些框架采用了兩種不同的方式:代碼生成和對(duì)象到XML映射。我將分別解釋這兩種方式。代碼生成方式使用代碼生成的框架包括XMLBeans、JAXB、Zeus和JBind。Castor也能使用這項(xiàng)技術(shù)。這類(lèi)框架的起點(diǎn)是描述文檔數(shù)據(jù)類(lèi)型的XML方案。使用框架提供的工具,就可以生成代表這些方案定義類(lèi)型的Java類(lèi)。最后,用這些生成的類(lèi)編寫(xiě)應(yīng)用程序,表示自己的模型數(shù)據(jù),并通過(guò)框架提供的一些輔助機(jī)制把數(shù)據(jù)序列化成XML。如果應(yīng)用程序要使用大型XML語(yǔ)法,那么代碼生成方式是個(gè)很好的方法。在數(shù)十個(gè)類(lèi)上編寫(xiě)定制XML序列化代碼的可伸縮性問(wèn)題由此消除。另一方面,也不再需要定義自己的JavaBean。框架生成的Java類(lèi)通常非常符合XML的結(jié)構(gòu),所以對(duì)它們進(jìn)行編碼很難。而且,生成的類(lèi)變成啞數(shù)據(jù)容器,因?yàn)橐话悴荒芟蛩鼈兲砑有袨?。一般?lái)說(shuō),在應(yīng)用程序代碼中要做些妥協(xié),才能很好地處理方案生成的類(lèi)型。另一個(gè)缺陷是如果修改方案,會(huì)造成生成的類(lèi)也要修改,所以也就會(huì)對(duì)圍繞它們編寫(xiě)的代碼帶來(lái)相應(yīng)的影響。這種類(lèi)型的XML綁定框架在數(shù)據(jù)拆解時(shí)最有用(例如,使用XML文檔并把它們轉(zhuǎn)化成Java對(duì)象)。除非擁有大型數(shù)據(jù)模型而且有可能從生成的類(lèi)中獲益,否則基于代碼生成的框架對(duì)于Ajax應(yīng)用程序來(lái)說(shuō)可能有很大的殺傷力。映射方式采用映射方式的框架包括Castor和ApacheCommonsBetwixt。映射通常是比代碼生成更靈活和更輕量的解決方案。首先,可以像通常一樣編寫(xiě)JavaBean,包括任何行為以及任何自己喜歡的方便的方法。然后,在運(yùn)行時(shí),調(diào)用框架中基于內(nèi)省的編排器,并根據(jù)對(duì)象成員的類(lèi)型、名稱和值生成XML文檔。通過(guò)定義類(lèi)的映射文件,可以覆蓋默認(rèn)的綁定策略,并就類(lèi)在XML中的表示方式對(duì)編排器提出建議。這種方法是在可伸縮性與靈活性之間的良好折中??梢园凑兆约合矚g的方式編寫(xiě)Java類(lèi),編排器負(fù)責(zé)處理XML。雖然映射定義文件編寫(xiě)起來(lái)簡(jiǎn)單,可伸縮性也足夠好,但是映射規(guī)則最多只能改變標(biāo)準(zhǔn)的綁定行為,而且在對(duì)象結(jié)構(gòu)和它們的XML表示之間總要?dú)埩粢恍詈?。最終,可能不得不在Java表示或XML格式之間任選一個(gè)做些折中,才能讓映射方法起作用。數(shù)據(jù)綁定總結(jié)DennisSosnoski就XML數(shù)據(jù)綁定API的主題,在代碼生成和代碼映射兩個(gè)方面寫(xiě)了深入的文章。如果想進(jìn)一步研究這個(gè)領(lǐng)域,我推薦他在Castor和代碼生成框架方面的精彩文章(請(qǐng)參閱
參考資料
中的鏈接)。總之,代碼生成方式損失了過(guò)多的靈活性和方便性,對(duì)于典型的Ajax應(yīng)用程序用處不大。另一方面,基于映射的框架可能工作得很好,但是要恰到好處地調(diào)整它們的映射策略,以便從對(duì)象生成需要的XML。所有的XML綁定API都具有手工序列化技術(shù)的一個(gè)主要不足:模型和視圖的耦合。被限制為一個(gè)類(lèi)型一個(gè)XML表示,就意味著在網(wǎng)絡(luò)上總要有冗余數(shù)據(jù)傳輸。更嚴(yán)重的問(wèn)題是,在情況要求客戶端代碼使用專(zhuān)門(mén)視圖時(shí),客戶端代碼卻無(wú)法得到它,所以可能要費(fèi)力地處理給定對(duì)象圖的一成不變的視圖。在傳統(tǒng)的Web應(yīng)用程序開(kāi)發(fā)中,采用頁(yè)面模板系統(tǒng)把視圖生成與控制器邏輯和模型數(shù)據(jù)干凈地分離。這種方法在Ajax場(chǎng)景中也會(huì)有幫助。頁(yè)面模板系統(tǒng)任何通用目的的頁(yè)面模板技術(shù)都可以用來(lái)生成XML,從而使Ajax應(yīng)用程序根據(jù)自己的數(shù)據(jù)模型生成任何XML響應(yīng)文檔。額外收獲是:模板可以用簡(jiǎn)單的、表現(xiàn)力強(qiáng)的標(biāo)記語(yǔ)言編寫(xiě),而不是用一行行的Java代碼編寫(xiě)。清單5是一個(gè)JSP頁(yè)面,采用了
Customer
bean并表示出定制的XML視圖,適合客戶端代碼生成訂單歷史組件。
清單4.生成訂單歷史文檔的JSP <xmlversion=""><%@pagecontentType="application/xml"%><%@tagliburi=""prefix="c"%><c:setvar="cust"value="${}"/><orderhistoryusername="${}"><c:forEachvar="order"items="${}"><orderid="${}"cost="${}"><date>${}</date><items><c:forEachvar="item"items="${}"><itemid="${}"><name><c:outvalue="${}"escapeXml="true"/></name><price>${}</price></item></c:forEach></items></order></c:forEach></orderhistory>這個(gè)簡(jiǎn)潔的模板只輸出訂單歷史視圖需要的數(shù)據(jù),不輸出不相關(guān)的資料(例如商品說(shuō)明)。創(chuàng)建產(chǎn)品搜索視圖的定制XML應(yīng)當(dāng)同樣簡(jiǎn)單,這個(gè)視圖包含每個(gè)商品的完整說(shuō)明和庫(kù)存水平。模板的問(wèn)題另一方面,現(xiàn)在我需要為每個(gè)不同視圖創(chuàng)建一個(gè)新JSP,而不能僅僅把需要的對(duì)象圖組織起來(lái)并序列化它。從設(shè)計(jì)的角度來(lái)說(shuō),許多人可能會(huì)有爭(zhēng)議,認(rèn)為這無(wú)論如何是件好事,因?yàn)檫@意味著正式地考慮服務(wù)器要生成的文檔類(lèi)型。而且,因?yàn)槲椰F(xiàn)在要處理通用的模板環(huán)境,而不是特定于XML的API,所以確保標(biāo)記匹配、元素和屬性的順序正確以及XML實(shí)體(例如
<
或
&)正確轉(zhuǎn)義就成了我的責(zé)任。JSP的核心
out
標(biāo)記使后面這項(xiàng)工作變得很容易,但是不是所有的模板技術(shù)都提供了這樣的機(jī)制。最后,沒(méi)有方便的途徑可以在服務(wù)器端根據(jù)方案檢驗(yàn)生成的XML文檔的正確性,但這畢竟不是要在生產(chǎn)環(huán)境中做的事,可以方便地在開(kāi)發(fā)期間處理它。不用XML的響應(yīng)數(shù)據(jù)迄今為止,我介紹的所有技術(shù)都用XML文檔的形式生成服務(wù)器響應(yīng)。但是,XML有一些問(wèn)題。其中一個(gè)就是延遲。瀏覽器不能立即解析XML文檔并生成DOM模型,所以這會(huì)降低某些Ajax組件需要的“迅捷”感,特別是在較慢的機(jī)器上解析大型文檔的時(shí)候更是如此?!艾F(xiàn)場(chǎng)搜索”就是一個(gè)示例,在這種搜索中,當(dāng)用戶輸入搜索術(shù)語(yǔ)時(shí),就會(huì)從服務(wù)器提取搜索結(jié)果并顯示給用戶。對(duì)于現(xiàn)場(chǎng)搜索組件來(lái)說(shuō),迅速地響應(yīng)輸入是非常重要的,但是同時(shí)它還需要迅速而持續(xù)地解析服務(wù)器的響應(yīng)。延遲是一個(gè)重要的考慮因素,但是避免使用XML的最大原因是差勁的客戶端DOMAPI。清單5顯示了使用跨瀏覽器兼容的方式通過(guò)DOM得到某個(gè)值的時(shí)候,通常不得不面對(duì)的困難。
清單5.在JavaScript中導(dǎo)航XML響應(yīng)文檔 用正則表達(dá)式處理XMLHttpRequest的responseText對(duì)象 varorderHistoryText=;varmatches=(/<date>(.*)<\/date>/);vardate=matches[1];在某些情況下,采用即時(shí)方式使用
responseText
會(huì)比較方便。但是,理想情況下,應(yīng)當(dāng)有種途徑,可以用一種能夠讓JavaScript輕松導(dǎo)航、卻沒(méi)有XML處理支出的格式表示復(fù)雜的結(jié)構(gòu)化數(shù)據(jù)。幸運(yùn)的是,確實(shí)存在這樣一種格式。JavaScript對(duì)象標(biāo)注實(shí)際上,JavaScript對(duì)象的大部分都由聯(lián)合數(shù)組、數(shù)字索引數(shù)組、字符串、數(shù)字或者這些類(lèi)型的嵌套組合而成。因?yàn)樗蓄?lèi)型都可以用JavaScript直接聲明,所以可以在一條語(yǔ)句中靜態(tài)地定義對(duì)象圖。清單7使用JSON語(yǔ)法聲明了一個(gè)對(duì)象,并演示了如何訪問(wèn)這個(gè)對(duì)象。大括號(hào)表示聯(lián)合數(shù)組(即對(duì)象),它的鍵-值組合由逗號(hào)分隔。方括號(hào)表示數(shù)字索引數(shù)組。
清單7.用JSON在JavaScript中直接聲明一個(gè)簡(jiǎn)單對(duì)象 varband={name:"TheBeatles",members:[{name:"John",instruments:["Vocals","Guitar","Piano"]},{name:"Paul",instruments:["Vocals","Bass","Piano","Guitar"]},{name:"George",instruments:["Guitar","Vocals"]},{name:"Ringo",instruments:["Drums","Vocals"]}]};Order類(lèi)的toJSONObject()方法實(shí)現(xiàn) publicJSONObjecttoJSONObject(){JSONObjectjson=newJSONObject();("id",id);("cost",getFormattedCost());("date",date);JSONArrayjsonItems=newJSONArray();for(Iterator<Item>iter=();();){().toJSONObject());}("items",jsonItems);returnjson;}可以看到,
API非常簡(jiǎn)單。
JSONObject
代表JavaScript對(duì)象(即聯(lián)合數(shù)組),有不同的
put()
方法,方法接受的
String
鍵和值是原生類(lèi)型、String
類(lèi)型或其他JSON類(lèi)型。JSONArray
代表索引數(shù)組,所以它的
put()
方法只接受一個(gè)值。請(qǐng)注意在清單8中,創(chuàng)建
jsonItems
數(shù)組,然后再用
put()
把它附加到
json
對(duì)象上;可以用另外一種方法做這項(xiàng)工作,就是對(duì)每個(gè)項(xiàng)目調(diào)用("items",().toJSONObject());。accumulate()
方法與
put()
類(lèi)似,區(qū)別在于它把值添加到按照鍵進(jìn)行識(shí)別的索引數(shù)組。清單9顯示了如何序列化
JSONObject
并把它寫(xiě)入servlet響應(yīng)。
清單9.從JSONObject生成序列化的JSON響應(yīng) publicvoiddoGet(HttpServletRequestreq,HttpServletResponseres)throwsServletException{ StringcustId=("username"); Customercustomer=getCustomer(custId); ("application/x-json"); ().print());}可以看到,它實(shí)際上什么也沒(méi)有做。在這里隱式調(diào)用的
JSONObject
的
toString()
方法做了所有工作。請(qǐng)注意,application/x-json
內(nèi)容類(lèi)型還有一點(diǎn)不確定——在編寫(xiě)這篇文章的時(shí)候,關(guān)于JSON應(yīng)當(dāng)屬于什么MIME類(lèi)型還沒(méi)有定論。但是,目前
application/x-json
是合理的選擇。清單10顯示了這個(gè)servlet代碼的示例響應(yīng)。
清單10.Customerbean的JSON表示 {"orders":[{"items":[{"price":"$","description":"512MegabyteType1CompactFlashcard.ManufacturedbyOolongIndustries","name":"Oolong512MBCFCard","id":"i-55768"},{"price":"$","description":"Megapixeldigitalcamerafeaturingsixshootingmodesand3xopticalzoom.Silver.","name":"FujakSuperpix72Camera","id":"i-74491"}],"date":"08-26-2005","cost":"$","id":"o-11123"}],"realname":"JamesHyrax","username":"jimmy66"}在客戶端使用JSON處理的最后一步是把在客戶端把JSON數(shù)據(jù)變成JavaScript對(duì)象。這可以通過(guò)對(duì)
eval()
的簡(jiǎn)單調(diào)用實(shí)現(xiàn),這個(gè)函數(shù)可以即時(shí)地解釋包含JavaScript表達(dá)式的字符串。清單11把JSON響應(yīng)轉(zhuǎn)變成JavaScript對(duì)象圖,然后執(zhí)行清單5的任務(wù),從顧客的最后一次訂單中得到第一個(gè)商品的名稱。
清單11.評(píng)估JSON響應(yīng) varjsonExpression="("++")";varcustomer=eval(jsonExpression);ame;比較清單11和
清單5
可以發(fā)現(xiàn)使用JSON的客戶端的優(yōu)勢(shì)。如果在Ajax項(xiàng)目中要在客戶端對(duì)許多復(fù)雜的服務(wù)器響應(yīng)進(jìn)行導(dǎo)航,那么JSON可能適合您的需要。JSON和
XMLHttpRequest
結(jié)合還會(huì)讓Ajax交互看起來(lái)更像RPC調(diào)用而不是SOA請(qǐng)求,這對(duì)應(yīng)用程序的設(shè)計(jì)可能會(huì)有意義。在下一篇文章中,我要研究的框架,就是明確地為了讓JavaScript代碼對(duì)服務(wù)器端對(duì)象進(jìn)行遠(yuǎn)程方法調(diào)用而設(shè)計(jì)的。JSON的不足JSON也有它的不足。使用這里介紹的JSON方式,就沒(méi)有辦法針對(duì)每個(gè)請(qǐng)求對(duì)對(duì)象的序列化進(jìn)行裁剪,所以不需要的字段可能經(jīng)常會(huì)在網(wǎng)絡(luò)上發(fā)送。另外,添加
toJSONObject()
方法到每個(gè)JavaBean,可伸縮性不太好,雖然用內(nèi)省和標(biāo)注編寫(xiě)一個(gè)通用的JavaBean到JSON的序列化器可能很簡(jiǎn)單。最后,如果服務(wù)器端代碼是面向服務(wù)的,沒(méi)有單獨(dú)針對(duì)處理Ajax客戶請(qǐng)求調(diào)整過(guò),那么由于對(duì)XML一致的支持,XML會(huì)是更好的選擇。比較序列化技術(shù)現(xiàn)在已經(jīng)看到了把Java狀態(tài)傳輸?shù)紸jax客戶端的五種不同技術(shù)。我討論了自行手工編碼XML序列化、通過(guò)代碼生成的XML綁定、通過(guò)映射機(jī)制的XML綁定、基于模板的XML生成以及手工編碼到JSON的序列化。每種技術(shù)都有自己的優(yōu)勢(shì)和不足,分別適用于不同的應(yīng)用程序架構(gòu)。為了總結(jié)每種方式的優(yōu)勢(shì)與不足,表1從六個(gè)方面進(jìn)行了粗略的評(píng)分:可伸縮性描述技術(shù)適應(yīng)大量數(shù)據(jù)類(lèi)型的容易程度。對(duì)于每個(gè)附加類(lèi)型,編碼和
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 品牌形象與營(yíng)銷(xiāo)策略匹配度評(píng)估表
- 醫(yī)藥冷鏈運(yùn)輸國(guó)際
- 能源企業(yè)社會(huì)責(zé)任報(bào)告編制指南
- 季度項(xiàng)目進(jìn)展及成果匯報(bào)會(huì)議紀(jì)實(shí)
- 血液腫瘤練習(xí)試題及答案
- 保育師初級(jí)復(fù)習(xí)試題有答案
- 物流配送中心庫(kù)存管理優(yōu)化方案
- 新品市場(chǎng)推廣策略與操作手冊(cè)
- 股份制辦公環(huán)境改善方案
- 病理學(xué)與病理生理學(xué)作業(yè)指導(dǎo)書(shū)
- 25種全球最流行的管理工具
- 道德與法治-五年級(jí)(下冊(cè))-《建立良好的公共秩序》教學(xué)課件
- 小學(xué)班主任工作經(jīng)驗(yàn)交流ppt
- 初中英語(yǔ)教學(xué)設(shè)計(jì)Its-time-to-watch-a-cartoon
- 2022年安徽高校教師崗前培訓(xùn)結(jié)業(yè)統(tǒng)考試題及參考答案
- 城市社區(qū)建設(shè)概論資料
- 水利監(jiān)理規(guī)劃(水利部)
- 數(shù)學(xué)-九宮數(shù)獨(dú)100題(附答案)
- 蘇教版四年級(jí)下冊(cè)科學(xué)全冊(cè)知識(shí)點(diǎn)總結(jié)
- 第三方單位考核管理辦法
- 造粒塔外壁清洗施工方案
評(píng)論
0/150
提交評(píng)論