面向 Java 開發(fā)人員的 Ajax: Ajax 的 Java 對(duì)象序列化在 Ajax 應(yīng)用程序中序列化數(shù)據(jù)的五種途徑 ![]() |
![]() | 級(jí)別: 中級(jí) Philip McCarthy, 軟件開發(fā)顧問(wèn), 獨(dú)立顧問(wèn) 2005 年 10 月 24 日 如果您正在使用異步 JavaScript 和 XML(Ajax)進(jìn)行 Java™ Web 開發(fā),那么您最關(guān)心的問(wèn)題可能就是把數(shù)據(jù)從服務(wù)器傳遞給客戶機(jī)。在 面向 Java 開發(fā)人員的 Ajax 系列的第二篇文章中,Philip McCarthy 介紹了 Java 對(duì)象序列化的五種方式,并提供了選擇最適合應(yīng)用程序的數(shù)據(jù)格式和技術(shù)所需要的全部信息。 在這個(gè)系列的 第一篇文章 中,我介紹了 Ajax 的構(gòu)造塊:
這一次,我將繼續(xù)討論 Ajax 開發(fā)的基礎(chǔ)知識(shí),但是將側(cè)重于許多 Java Web 開發(fā)人員最關(guān)心的問(wèn)題:為客戶機(jī)生成數(shù)據(jù)。 多數(shù) Java 開發(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è)面,從而更新用戶界面。但是,在 Java Web 應(yīng)用程序使用 Ajax UI 的情況下,基于從 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ì)象圖極為容易。 我將使用一個(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 格式開始討論。
把 Ajax 響應(yīng)作為 XML 來(lái)傳遞有許多原因:每個(gè)支持 Ajax 的瀏覽器都有導(dǎo)航 XML 文檔的方法,也有許多服務(wù)器端技術(shù)可以處理 XML 數(shù)據(jù)。通過(guò)制定一個(gè)方案,描述要交換的文檔類型,在 Ajax 客戶端和服務(wù)器端之間很容易定義合約,而且如果服務(wù)器端架構(gòu)采用面向服務(wù)的方式,那么使用 XML 也可以允許非 Ajax 客戶機(jī)使用您提供的數(shù)據(jù)。 我將考慮從 Java 對(duì)象產(chǎn)生 XML 數(shù)據(jù)的三種方法,并討論每種方法的優(yōu)劣。
首先,可以從對(duì)象圖以編程的方式生成 XML。這種方式可以簡(jiǎn)單到只是在每個(gè) JavaBean 類中實(shí)現(xiàn) toXml() 方法即可。然后就可以選擇合適的 XML API,讓每個(gè) bean 提供表示自己狀態(tài)的元素,并遞歸地對(duì)自己的成員調(diào)用對(duì)象圖。顯然,這種方式無(wú)法擴(kuò)展到大量的類,因?yàn)槊總€(gè)類都需要專門編寫自己的 XML 生成代碼。從好的方面來(lái)看,這是一個(gè)實(shí)現(xiàn)起來(lái)簡(jiǎn)單的方式,沒有額外的配置支出或者更復(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è) XML API 可以替您做這些工作,這樣您就可以把精力集中在 XML 的內(nèi)容上。清單 1 用 JDOM API 實(shí)現(xiàn)了在線商店示例中表示訂單的類中的 toXml()(請(qǐng)參閱 圖 1)。 清單 1. Order 類的 toXml() 的 JDOM 實(shí)現(xiàn)
在這里可以看到用 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)
JDOM 再次把工作變得非常簡(jiǎn)單。只需要在對(duì)象圖返回的 XML 元素外面包裝一個(gè) Document,然后用 XMLOutputter 把文檔寫入 servlet 響應(yīng)即可。清單 3 顯示了用這種方式生成的 XML 示例,用 JDOM Format.getPrettyFormat() 對(duì) XMLOutputter 進(jìn)行初始化,格式化得非常好。在這個(gè)示例中,顧客只做了一個(gè)訂單,包含兩個(gè)商品。 清單 3. 代表顧客的 XML 文檔
有趣的是,清單 3 中的代碼展示了讓 JavaBean 把自己序列化為 XML 的一個(gè)主要不足。假設(shè)要用這個(gè)文檔表示顧客的訂單歷史視圖。在這種情況下,不太可能要顯示每個(gè)歷史訂單中每個(gè)商品的完整說(shuō)明,或者告訴顧客他或她自己的姓名。但是如果應(yīng)用程序有一個(gè) ProductSearch 類,它就是以 Item bean 列表的形式返回搜索結(jié)果,那么在 Item 的 XML 表示中包含說(shuō)明可能會(huì)有幫助。而且,Item 類上代表當(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 類獨(dú)立變化。例如,對(duì)顧客文檔的方案做修改,可能會(huì)影響多個(gè) Java 類,造成它們也不得不做修改和重新編譯。 我稍后會(huì)解決這些問(wèn)題,但是首先來(lái)看一個(gè)對(duì)自行序列化方式的可伸縮性問(wèn)題的解決方案:XML 綁定框架。
近些年來(lái),已經(jīng)開發(fā)了多個(gè) Java API 來(lái)簡(jiǎn)化 XML 文檔到 Java 對(duì)象圖的綁定過(guò)程。多數(shù)都提供了 XML 編排和拆解;也就是說(shuō),它們可以在 Java 對(duì)象圖和 XML 之間執(zhí)行雙向會(huì)話。這些框架封裝了 XML 處理的全部工作,這意味著應(yīng)用程序代碼只需要處理普通的 Java 類。它們還希望提供有用的輔助功能,例如文檔驗(yàn)證。籠統(tǒng)來(lái)說(shuō),這些框架采用了兩種不同的方式:代碼生成和對(duì)象到 XML 映射。我將分別解釋這兩種方式。 使用代碼生成的框架包括 XMLBeans、JAXB、Zeus 和 JBind。Castor 也能使用這項(xiàng)技術(shù)。這類框架的起點(diǎn)是描述文檔數(shù)據(jù)類型的 XML 方案。使用框架提供的工具,就可以生成代表這些方案定義類型的 Java 類。最后,用這些生成的類編寫應(yīng)用程序,表示自己的模型數(shù)據(jù),并通過(guò)框架提供的一些輔助機(jī)制把數(shù)據(jù)序列化成 XML。 如果應(yīng)用程序要使用大型 XML 語(yǔ)法,那么代碼生成方式是個(gè)很好的方法。在數(shù)十個(gè)類上編寫定制 XML 序列化代碼的可伸縮性問(wèn)題由此消除。另一方面,也不再需要定義自己的 JavaBean??蚣苌傻?Java 類通常非常符合 XML 的結(jié)構(gòu),所以對(duì)它們進(jìn)行編碼很難。而且,生成的類變成啞數(shù)據(jù)容器,因?yàn)橐话悴荒芟蛩鼈兲砑有袨?。一般?lái)說(shuō),在應(yīng)用程序代碼中要做些妥協(xié),才能很好地處理方案生成的類型。另一個(gè)缺陷是如果修改方案,會(huì)造成生成的類也要修改,所以也就會(huì)對(duì)圍繞它們編寫的代碼帶來(lái)相應(yīng)的影響。 這種類型的 XML 綁定框架在數(shù)據(jù)拆解時(shí)最有用(例如,使用 XML 文檔并把它們轉(zhuǎn)化成 Java 對(duì)象)。除非擁有大型數(shù)據(jù)模型而且有可能從生成的類中獲益,否則基于代碼生成的框架對(duì)于 Ajax 應(yīng)用程序來(lái)說(shuō)可能有很大的殺傷力。 采用映射方式的框架包括 Castor 和 Apache Commons Betwixt。映射通常是比代碼生成更靈活和更輕量的解決方案。首先,可以像通常一樣編寫 JavaBean,包括任何行為以及任何自己喜歡的方便的方法。然后,在運(yùn)行時(shí),調(diào)用框架中基于內(nèi)省的編排器,并根據(jù)對(duì)象成員的類型、名稱和值生成 XML 文檔。通過(guò)定義類的映射文件,可以覆蓋默認(rèn)的綁定策略,并就類在 XML 中的表示方式對(duì)編排器提出建議。 這種方法是在可伸縮性與靈活性之間的良好折中??梢园凑兆约合矚g的方式編寫 Java 類,編排器負(fù)責(zé)處理 XML。雖然映射定義文件編寫起來(lái)簡(jiǎn)單,可伸縮性也足夠好,但是映射規(guī)則最多只能改變標(biāo)準(zhǔn)的綁定行為,而且在對(duì)象結(jié)構(gòu)和它們的 XML 表示之間總要?dú)埩粢恍詈?。最終,可能不得不在 Java 表示或 XML 格式之間任選一個(gè)做些折中,才能讓映射方法起作用。 Dennis Sosnoski 就 XML 數(shù)據(jù)綁定 API 的主題,在代碼生成和代碼映射兩個(gè)方面寫了深入的文章。如果想進(jìn)一步研究這個(gè)領(lǐng)域,我推薦他在 Castor 和代碼生成框架方面的精彩文章(請(qǐng)參閱 參考資料 中的鏈接)。 總之,代碼生成方式損失了過(guò)多的靈活性和方便性,對(duì)于典型的 Ajax 應(yīng)用程序用處不大。另一方面,基于映射的框架可能工作得很好,但是要恰到好處地調(diào)整它們的映射策略,以便從對(duì)象生成需要的 XML。 所有的 XML 綁定 API 都具有手工序列化技術(shù)的一個(gè)主要不足:模型和視圖的耦合。被限制為一個(gè)類型一個(gè) XML 表示,就意味著在網(wǎng)絡(luò)上總要有冗余數(shù)據(jù)傳輸。更嚴(yán)重的問(wèn)題是,在情況要求客戶端代碼使用專門視圖時(shí),客戶端代碼卻無(wú)法得到它,所以可能要費(fèi)力地處理給定對(duì)象圖的一成不變的視圖。 在傳統(tǒng)的 Web 應(yīng)用程序開發(fā)中,采用頁(yè)面模板系統(tǒng)把視圖生成與控制器邏輯和模型數(shù)據(jù)干凈地分離。這種方法在 Ajax 場(chǎng)景中也會(huì)有幫助。
任何通用目的的頁(yè)面模板技術(shù)都可以用來(lái)生成 XML,從而使 Ajax 應(yīng)用程序根據(jù)自己的數(shù)據(jù)模型生成任何 XML 響應(yīng)文檔。額外收獲是:模板可以用簡(jiǎn)單的、表現(xiàn)力強(qiáng)的標(biāo)記語(yǔ)言編寫,而不是用一行行的 Java 代碼編寫。清單 5 是一個(gè) JSP 頁(yè)面,采用了 Customer bean 并表示出定制的 XML 視圖,適合客戶端代碼生成訂單歷史組件。 清單 4. 生成訂單歷史文檔的 JSP
這個(gè)簡(jiǎn)潔的模板只輸出訂單歷史視圖需要的數(shù)據(jù),不輸出不相關(guān)的資料(例如商品說(shuō)明)。創(chuàng)建產(chǎn)品搜索視圖的定制 XML 應(yīng)當(dāng)同樣簡(jiǎn)單,這個(gè)視圖包含每個(gè)商品的完整說(shuō)明和庫(kù)存水平。 另一方面,現(xiàn)在我需要為每個(gè)不同視圖創(chuàng)建一個(gè)新 JSP,而不能僅僅把需要的對(duì)象圖組織起來(lái)并序列化它。從設(shè)計(jì)的角度來(lái)說(shuō),許多人可能會(huì)有爭(zhēng)議,認(rèn)為這無(wú)論如何是件好事,因?yàn)檫@意味著正式地考慮服務(wù)器要生成的文檔類型。而且,因?yàn)槲椰F(xiàn)在要處理通用的模板環(huán)境,而不是特定于 XML 的 API,所以確保標(biāo)記匹配、元素和屬性的順序正確以及 XML 實(shí)體(例如 < 或 &)正確轉(zhuǎn)義就成了我的責(zé)任。JSP 的核心 out 標(biāo)記使后面這項(xiàng)工作變得很容易,但是不是所有的模板技術(shù)都提供了這樣的機(jī)制。最后,沒有方便的途徑可以在服務(wù)器端根據(jù)方案檢驗(yàn)生成的 XML 文檔的正確性,但這畢竟不是要在生產(chǎn)環(huán)境中做的事,可以方便地在開發(fā)期間處理它。
迄今為止,我介紹的所有技術(shù)都用 XML 文檔的形式生成服務(wù)器響應(yīng)。但是,XML 有一些問(wèn)題。其中一個(gè)就是延遲。瀏覽器不能立即解析 XML 文檔并生成 DOM 模型,所以這會(huì)降低某些 Ajax 組件需要的“迅捷”感,特別是在較慢的機(jī)器上解析大型文檔的時(shí)候更是如此。“現(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 的最大原因是差勁的客戶端 DOM API。清單 5 顯示了使用跨瀏覽器兼容的方式通過(guò) DOM 得到某個(gè)值的時(shí)候,通常不得不面對(duì)的困難。 清單 5. 在 JavaScript 中導(dǎo)航 XML 響應(yīng)文檔
當(dāng)元素中間存在空白時(shí),情況就變得更加復(fù)雜,因?yàn)槊總€(gè)元素的 firstChild 經(jīng)常是個(gè)空白文本節(jié)點(diǎn)?,F(xiàn)在有 JavaScript 庫(kù)可以緩解處理 XML 文檔的麻煩。這些庫(kù)包括 Sarissa (請(qǐng)參閱 參考資料)和 Google-ajaXSLT,這兩個(gè)庫(kù)都把 XPath 功能添加到了大多數(shù)瀏覽器中。 但是,想想替代方案還是值得的。除了 responseXML 之外,XMLHttpRequest 對(duì)象還提供了名為 responseText 的屬性,這個(gè)屬性只是以字符串的方式提供服務(wù)器的響應(yīng)體。 當(dāng)服務(wù)器需要向客戶機(jī)發(fā)送非常簡(jiǎn)單的值時(shí),responseText 特別方便,它可以避免 XML 導(dǎo)致的帶寬支出和處理支出。例如,簡(jiǎn)單的 true/false 響應(yīng)可以由服務(wù)器以純文本方式返回,可以是逗號(hào)分隔的簡(jiǎn)單的名稱或數(shù)字列表。但是,一般來(lái)說(shuō),最好不要在同一個(gè)應(yīng)用程序中把 XML 響應(yīng)和純文本響應(yīng)混合使用;保持單一數(shù)據(jù)格式可以讓代碼抽象和重用更加簡(jiǎn)單。 responseText 與 XML 響應(yīng)數(shù)據(jù)結(jié)合時(shí)也會(huì)有用。在只需要從響應(yīng)文檔中提取單一值的場(chǎng)景中,“欺騙性”地把 XML 當(dāng)作文本字符串,而不把它當(dāng)作結(jié)構(gòu)化的文檔對(duì)待,會(huì)更方便。例如,清單 6 顯示了如何用正則表達(dá)式從顧客的訂單歷史中提取第一筆訂單的日期。不過(guò),這實(shí)際是種花招,一般不應(yīng)當(dāng)依賴 XML 文檔的詞匯表達(dá)。 清單 6. 用正則表達(dá)式處理 XMLHttpRequest 的 responseText 對(duì)象
在某些情況下,采用即時(shí)方式使用 responseText 會(huì)比較方便。但是,理想情況下,應(yīng)當(dāng)有種途徑,可以用一種能夠讓 JavaScript 輕松導(dǎo)航、卻沒有 XML 處理支出的格式表示復(fù)雜的結(jié)構(gòu)化數(shù)據(jù)。幸運(yùn)的是,確實(shí)存在這樣一種格式。
實(shí)際上,JavaScript 對(duì)象的大部分都由聯(lián)合數(shù)組、數(shù)字索引數(shù)組、字符串、數(shù)字或者這些類型的嵌套組合而成。因?yàn)樗蓄愋投伎梢杂?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ì)象
既然 JSON 是一個(gè)有趣的語(yǔ)言特性,那么它對(duì) Ajax 有什么意義呢?妙處在于可以用 JSON 在 Ajax 服務(wù)器響應(yīng)中通過(guò)網(wǎng)絡(luò)發(fā)送 JavaScript 對(duì)象圖。這意味著在客戶端可以避免使用笨拙的 DOM API 對(duì) XML 進(jìn)行導(dǎo)航 —— 只需要分析 JSON 響應(yīng),就會(huì)立即得到可以訪問(wèn)的 JavaScript 對(duì)象圖。但是,首先需要把 JavaBean 變成 JSON。 不同 XML 生成技術(shù)所具有的優(yōu)缺點(diǎn)也適用于 JSON 的產(chǎn)生。而且可以證明,存在需要再次使用表示模板技術(shù)的情況。但是,使用 JSON 在理念上更接近于在應(yīng)用層之間傳遞序列化的對(duì)象,而不是創(chuàng)建應(yīng)用程序狀態(tài)的視圖。我將介紹如何用 org.json 這個(gè) Java API 在 Java 類上創(chuàng)建 toJSONObject() 方法。然后,就可以把 JSONObject 簡(jiǎn)單地序列化成 JSON。清單 8 反映了 清單 1 討論的 XML,顯示了 Order 類的 toJSONObject() 實(shí)現(xiàn)。 清單 8. Order 類的 toJSONObject() 方法實(shí)現(xiàn)
可以看到,org.json API 非常簡(jiǎn)單。 JSONObject 代表 JavaScript 對(duì)象(即聯(lián)合數(shù)組),有不同的 put() 方法,方法接受的 String 鍵和值是原生類型、String 類型或其他 JSON 類型。JSONArray 代表索引數(shù)組,所以它的 put() 方法只接受一個(gè)值。請(qǐng)注意在清單 8 中,創(chuàng)建 jsonItems 數(shù)組,然后再用 put() 把它附加到 json 對(duì)象上;可以用另外一種方法做這項(xiàng)工作,就是對(duì)每個(gè)項(xiàng)目調(diào)用 json.accumulate("items",iter.next().toJSONObject());。accumulate() 方法與 put() 類似,區(qū)別在于它把值添加到按照鍵進(jìn)行識(shí)別的索引數(shù)組。 清單 9 顯示了如何序列化 JSONObject 并把它寫入 servlet 響應(yīng)。 清單 9. 從 JSONObject 生成序列化的 JSON 響應(yīng)
可以看到,它實(shí)際上什么也沒有做。在這里隱式調(diào)用的 JSONObject 的 toString() 方法做了所有工作。請(qǐng)注意,application/x-json 內(nèi)容類型還有一點(diǎn)不確定 —— 在編寫這篇文章的時(shí)候,關(guān)于 JSON 應(yīng)當(dāng)屬于什么 MIME 類型還沒有定論。但是,目前 application/x-json 是合理的選擇。清單 10 顯示了這個(gè) servlet 代碼的示例響應(yīng)。 清單 10. Customer bean 的 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)
比較清單 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 方式,就沒有辦法針對(duì)每個(gè)請(qǐng)求對(duì)對(duì)象的序列化進(jìn)行裁剪,所以不需要的字段可能經(jīng)常會(huì)在網(wǎng)絡(luò)上發(fā)送。另外,添加 toJSONObject() 方法到每個(gè) JavaBean,可伸縮性不太好,雖然用內(nèi)省和標(biāo)注編寫一個(gè)通用的 JavaBean 到 JSON 的序列化器可能很簡(jiǎn)單。最后,如果服務(wù)器端代碼是面向服務(wù)的,沒有單獨(dú)針對(duì)處理 Ajax 客戶請(qǐng)求調(diào)整過(guò),那么由于對(duì) XML 一致的支持,XML 會(huì)是更好的選擇。
現(xiàn)在已經(jīng)看到了把 Java 狀態(tài)傳輸?shù)?Ajax 客戶端的五種不同技術(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)分:
表 1 中的數(shù)據(jù)并不表明某項(xiàng)序列化技術(shù)比其他的技術(shù)好。畢竟,六種標(biāo)準(zhǔn)的相對(duì)重要性取決于項(xiàng)目的具體情況。例如,如果要處理數(shù)百種數(shù)據(jù)類型,這時(shí)想要的是可伸縮性,那么代碼生成可能就是最好的選擇。如果需要為同一數(shù)據(jù)模型生成多個(gè)不同視圖,那么就應(yīng)當(dāng)使用頁(yè)面模板。如果處理的是小規(guī)模項(xiàng)目,想降低需要編寫的 JavaScript 代碼數(shù)量,那么請(qǐng)考慮 JSON。 希望這篇文章為您提供了選擇適合自己應(yīng)用程序的序列化技術(shù)所需要的信息。請(qǐng)參閱 參考資料 一節(jié),學(xué)習(xí)關(guān)于這里討論的技術(shù)的更多內(nèi)容。您還應(yīng)當(dāng)繼續(xù)關(guān)注這個(gè)系列的下一篇文章,在下一篇文章中,我將介紹如何用直接 Web 遠(yuǎn)程(DWR)編寫 Java Ajax 應(yīng)用程序。DWR 框架支持從 JavaScript 代碼中直接調(diào)用 Java 類上的方法。換句話說(shuō),它替您負(fù)責(zé)數(shù)據(jù)序列化的工作,所以您可以在更高的抽象層次上使用 Ajax。
學(xué)習(xí)
獲得產(chǎn)品和技術(shù)
討論
|
聯(lián)系客服