IBM®
直接進入主要内容
    Taiwan  [選擇 ]      使用條款
 
 
    
     首頁      產品      服務與解决方案      技術支援與下載      個人專區     
直接進入主要内容

developerWorks 台灣  >  Java technology  >

Java 導向開發人員的 Ajax: Ajax 的 Java 物件序列化

在 Ajax 應用程序中序列化資料的五種途徑

developerWorks
文件選項

需要JavaScript的文件選項無法顯示

討論


級別: 中級

Philip McCarthy, 軟體開發顧問, 獨立顧問

2005 年 10 月 24 日

如果您正在使用非同步 JavaScript 和 XML(Ajax)進行 Java™ Web 開發,那麼您最關心的問題可能就是把資料從伺服器傳遞給使用者端。在 Java 導向 開發人員的 Ajax 系列的第二篇文章中,Philip McCarthy 介紹了 Java 物件序列化的五種方式,並提供了選擇最適合應用程序的資料格式和技術所需要的全部信息。

在這個系列的 第一篇文章 中,我介紹了 Ajax 的構造塊:

  • 如何用 JavaScript XMLHttpRequest 物件從 Web 頁面向伺服器發送非同步請求。
  • 如何用 Java servlet 處理和響應請求(向使用者端傳回 XML 文件)。
  • 如何在用戶端用響應文件更新頁面視圖。

這一次,我將繼續討論 Ajax 開發的基礎知識,但是將側重於許多 Java Web 開發人員最關心的問題:為使用者端產生資料。

多數 Java 開發人員已經把模型-視圖-控制器(MVC)模式應用在他們的 Web 應用程序上。在傳統的 Web 應用程序中,視圖元件由 JSP 或者其他表示技術(例如 Velocity 樣板)構成。這些表示元件動態地產生全新的 HTML 頁面,替代用戶以前正在檢視的頁面,進而更新用戶界面。但是,在 Java Web 應用程序使用 Ajax UI 的情況下,基於從 XMLHttpRequest 的響應接收到的資料,JavaScript 用戶端程式碼對於更新用戶看到的內容負有最終責任。從伺服器的角度來看,視圖成為它響應使用者端請求而發送的資料表示。

這篇文章側重於可以用來產生 Java 物件以資料為中心的視圖的技術。我將示範可以把 JavaBeans 變成 XML 文件的各種方法,並且討論每種方法的優劣。您將看到為什麼 XML 並不總是最好的途徑:對於簡單的 Ajax 請求來說,傳輸純文件更好。最後,我將介紹 JavaScript 物件表示法(JSON)。JSON 允許資料以序列化的 JavaScript 物件圖的形式傳輸,在用戶端程式碼中處理序列化的 JavaScript 物件圖極為容易。

關於範例

我將使用一個範例應用程序和幾個使用案例來示範這裡討論的技術特性和技術。圖 1 顯示的極為簡單的資料模型可以表示範例使用案例。這個模型代表在線商店中的顧客帳戶。顧客擁有以前訂單的集合,每個訂單包含幾個商品。


圖 1. 簡單的對象模型
代表顧客帳戶的對象模型

雖然 XMLHttpRequest 對於發送資料使用的格式沒有做任何限制,但是對於多數目的來說,只發送傳統的表單資料是適合的,所以我的討論集中在伺服器的響應上。響應也可以有基於文件的格式,但是正如它的名字表示的,XMLHttpRequest 具有內置的處理 XML 響應資料的能力。這使 XML 成為 Ajax 響應的預設選擇,所以我們從 XML 格式開始討論。



回到頂端


從 Java 類別產生 XML

把 Ajax 響應作為 XML 來傳遞有許多原因:每個支援 Ajax 的瀏覽器都有導航 XML 文件的方法,也有許多伺服器端技術可以處理 XML 資料。透過制定一個方案,描述要交換的文件類型,在 Ajax 用戶端和伺服器端之間很容易定義合約,而且如果伺服器端架構採用服務導向的方式,那麼使用 XML 也可以允許非 Ajax 使用者端使用您提供的資料。

我將考慮從 Java 物件產生 XML 資料的三種方法,並討論每種方法的優劣。



回到頂端


自行進行序列化

首先,可以從物件圖以程式設計的方式產生 XML。這種方式可以簡單到只是在每個 JavaBean 類別中實作 toXml() 方法即可。然後就可以選擇合適的 XML API,讓每個 bean 提供表示自己狀態的元素,並遞歸地對自己的成員呼叫物件圖。顯然,這種方式無法擴充到大量的類別,因為每個類別都需要專門撰寫自己的 XML 產生程式碼。從好的方面來看,這是一個實作起來簡單的方式,沒有額外的設定支出或者更複雜的建立過程支出,任何 JavaBean 圖都可以只用幾個呼叫就變成 XML 文件。

在本系列 前一篇文章 的範例程式碼中,我把 XML 標記字符串連接在一起,實作了 toXml() 方法。上次我就提到過,這是個糟糕的方法,因為它把確保標記配對、實體編碼等工作的負擔放在每個 toXml() 方法的程式碼中。在 Java 平台上有幾個 XML API 可以替您做這些工作,這樣您就可以把精力集中在 XML 的內容上。清單 1 用 JDOM API 實作了在線商店範例中表示訂單的類別中的 toXml()(請參閱 圖 1)。


清單 1. Order 類別的 toXml() 的 JDOM 實作

				
public Element toXml() {

  Element elOrder = new Element("order");
  elOrder.setAttribute("id",id);

  elOrder.setAttribute("cost",getFormattedCost());

  Element elDate = new Element("date").addContent(date);
  elOrder.addContent(elDate);

  Element elItems = new Element("items");
  for (Iterator<Item> iter = 
   items.iterator() ; iter.hasNext() ; ) {
    elItems.addContent(iter.next().toXml());
  }
  elOrder.addContent(elItems);

  return elOrder;
}

在這裡可以看到用 JDOM 建立元素、使用屬性和加入元素內容有多麼簡單。遞歸地呼叫復合 JavaBean 的 toXml() 方法是為了取得它們子圖的 Element 表示。例如,items 元素的內容是透過呼叫 Order 聚合的每個 Item 物件上的 toXml() 得到的。

一旦所有的 JavaBean 都實作了 toXml() 方法,那麼把任意物件圖序列化成 XML 文件並傳回給 Ajax 使用者端就簡單了,如清單 2 所示。


清單 2. 從 JDOM 元素產生 XML 響應

				
public void doGet(HttpServletRequest req, HttpServletResponse res)
  throws java.io.IOException, ServletException {

    String custId = req.getParameter("username");
    Customer customer = getCustomer(custId);

    Element responseElem = customer.toXml();
    Document responseDoc = new Document(responseElem);

    res.setContentType("application/xml");
    new XMLOutputter().output(responseDoc,res.getWriter());
}

JDOM 再次把工作變得非常簡單。只需要在物件圖傳回的 XML 元素外面包裝一個 Document,然後用 XMLOutputter 把文件寫入 servlet 響應即可。清單 3 顯示了用這種方式產生的 XML 範例,用 JDOM Format.getPrettyFormat()XMLOutputter 進行初始化,格式化得非常好。在這個範例中,顧客只做了一個訂單,包含兩個商品。


清單 3. 代表顧客的 XML 文件

				
<?xml version="1.0" encoding="UTF-8"?>
<customer username="jimmy66">
  <realname>James Hyrax</realname>
  <orders>
    <order id="o-11123" cost="$349.98">
      <date>08-26-2005</date>
      <items>
        <item id="i-55768">
          <name>Oolong 512MB CF Card</name>
          <description>512 Megabyte Type 1 CompactFlash card. 
          Manufactured by Oolong Industries</description>
          <price>$49.99</price>
        </item>
        <item id="i-74491">
          <name>Fujak Superpix72 Camera</name>
          <description>7.2 Megapixel digital camera featuring six 
          shooting modes and 3x optical zoom. Silver.</description>
          <price>$299.99</price>
        </item>
      </items>
    </order>
  </orders>
</customer>

自行序列化的不足

有趣的是,清單 3 中的程式碼展示了讓 JavaBean 把自己序列化為 XML 的一個主要不足。假設要用這個文件表示顧客的訂單歷史視圖。在這種情況下,不太可能要顯示每個歷史訂單中每個商品的完整說明,或者告訴顧客他或她自己的姓名。但是如果應用程序有一個 ProductSearch 類別,它就是以 Item bean 列表的形式傳回搜索結果,那麼在 Item 的 XML 表示中包含說明可能會有幫助。而且,Item 類別上代表目前庫存水平的額外字段,在產品搜索視圖中可能就是需要顯示的有用信息。但是,不管目前的庫存水平是否與目前情況相關(比如對顧客的訂單歷史來說),這個字段都會從包含 Item 的任何物件圖中序列化出來。

從設計的角度來看,這是資料模型與視圖產生耦合的經典問題。每個 bean 只能用一種途徑序列化自己,一成不變的方式意味著 Ajax 互動最終要交換它們不需要交換的資料,因此造成用戶端程式碼要從文件中找到需要的信息更加困難,而且也會增加帶寬消耗和用戶端的 XML 解析時間。這種耦合的另一個後果就是 XML 的語法不能脫離 Java 類別獨立變化。例如,對顧客文件的方案做修改,可能會影響多個 Java 類別,造成它們也不得不做修改和重新編譯。

我稍後會解決這些問題,但是首先來看一個對自行序列化方式的可伸縮性問題的解決方案:XML 繫結框架。



回到頂端


XML 繫結框架

近些年來,已經開發了多個 Java API 來簡化 XML 文件到 Java 物件圖的繫結過程。多數都提供了 XML 編排和拆解;也就是說,它們可以在 Java 物件圖和 XML 之間執行雙向會話。這些框架封裝了 XML 處理的全部工作,這意味著應用程序程式碼只需要處理普通的 Java 類別。它們還希望提供有用的輔助功能,例如文件驗證。籠統來說,這些框架採用了兩種不同的方式:程式碼產生和物件到 XML 對應。我將分別解釋這兩種方式。

程式碼產生方式

使用程式碼產生的框架包括 XMLBeans、JAXB、Zeus 和 JBind。Castor 也能使用這項技術。這類框架的起點是描述文件資料類型的 XML 方案。使用框架提供的工具,就可以產生代表這些方案定義類型的 Java 類別。最後,用這些產生的類別撰寫應用程序,表示自己的模型資料,並透過框架提供的一些輔助機制把資料序列化成 XML。

如果應用程序要使用大型 XML 語法,那麼程式碼產生方式是個很好的方法。在數十個類別上撰寫制定 XML 序列化程式碼的可伸縮性問題由此消除。另一方面,也不再需要定義自己的 JavaBean。框架產生的 Java 類別通常非常符合 XML 的結構,所以對它們進行編碼很難。而且,產生的類別變成啞資料容器,因為一般不能向它們加入行為。一般來說,在應用程序程式碼中要做些妥協,才能很好地處理方案產生的類型。另一個缺陷是如果修改方案,會造成產生的類別也要修改,所以也就會對圍繞它們撰寫的程式碼帶來相應的影響。

這種類型的 XML 繫結框架在資料拆解時最有用(例如,使用 XML 文件並把它們轉化成 Java 物件)。除非擁有大型資料模型而且有可能從產生的類別中獲益,否則基於程式碼產生的框架對於 Ajax 應用程序來說可能有很大的殺傷力。

對應方式

採用對應方式的框架包括 Castor 和 Apache Commons Betwixt。對應通常是比程式碼產生更靈活和更輕量的解決方案。首先,可以像通常一樣撰寫 JavaBean,包括任何行為以及任何自己喜歡的方便的方法。然後,在執行時,呼叫框架中基於預設的編排器,並根據物件成員的類型、名稱和值產生 XML 文件。透過定義類別的對應文件,可以覆蓋預設的繫結策略,並就類別在 XML 中的表示方式對編排器提出建議。

這種方法是在可伸縮性與靈活性之間的良好折中。可以按照自己喜歡的方式撰寫 Java 類別,編排器負責處理 XML。雖然對應定義文件撰寫起來簡單,可伸縮性也足夠好,但是對應規則最多只能改變標準的繫結行為,而且在物件結構和它們的 XML 表示之間總要殘留一些耦合。最終,可能不得不在 Java 表示或 XML 格式之間任選一個做些折中,才能讓對應方法起作用。

資料繫結總結

Dennis Sosnoski 就 XML 資料繫結 API 的主題,在程式碼產生和程式碼對應兩個方面寫了深入的文章。如果想進一步研究這個領域,我推薦他在 Castor 和程式碼產生框架方面的精彩文章(請參閱 參考資料 中的連結)。

總之,程式碼產生方式損失了過多的靈活性和方便性,對於典型的 Ajax 應用程序用處不大。另一方面,基於對應的框架可能工作得很好,但是要恰到好處地調整它們的對應策略,以便從物件產生需要的 XML。

所有的 XML 繫結 API 都具有手工序列化技術的一個主要不足:模型和視圖的耦合。被限制為一個類型一個 XML 表示,就意味著在網路上總要有冗餘資料傳輸。更嚴重的問題是,在情況要求用戶端程式碼使用專門視圖時,用戶端程式碼卻無法得到它,所以可能要費力地處理給定物件圖的一成不變的視圖。

在傳統的 Web 應用程序開發中,採用頁面樣板系統把視圖產生與控制器邏輯和模型資料乾淨地分離。這種方法在 Ajax 場景中也會有幫助。



回到頂端


頁面樣板系統

任何通用目的的頁面樣板技術都可以用來產生 XML,進而使 Ajax 應用程序根據自己的資料模型產生任何 XML 響應文件。額外收穫是:樣板可以用簡單的、表現力強的標記語言撰寫,而不是用一行行的 Java 程式碼撰寫。清單 5 是一個 JSP 頁面,採用了 Customer bean 並表示出制定的 XML 視圖,適合用戶端程式碼產生訂單歷史元件。


清單 4. 產生訂單歷史文件的 JSP

				
<?xml version="1.0"?>
<%@ page contentType="application/xml" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="cust" value="${requestScope.customer}"/>

<orderhistory username="${cust.username}">
<c:forEach var="order" items="${cust.orders}">
  <order id="${order.id}" cost="${order.formattedCost}">
    <date>${order.date}</date>
    <items>
    <c:forEach var="item" items="${order.items}">
      <item id="${item.id}">
        <name><c:out value="${item.name}" escapeXml="true"/></name>
        <price>${item.formattedPrice}</price>
      </item>
    </c:forEach>
    </items>
  </order>
</c:forEach>
</orderhistory>

這個簡潔的樣板只輸出訂單歷史視圖需要的資料,不輸出不相關的資料(例如商品說明)。建立產品搜索視圖的制定 XML 應當同樣簡單,這個視圖包含每個商品的完整說明和庫存水平。

樣板的問題

另一方面,現在我需要為每個不同視圖建立一個新 JSP,而不能僅僅把需要的對象圖組織起來並序列化它。從設計的角度來說,許多人可能會有爭議,認為這無論如何是件好事,因為這意味著正式地考慮伺服器要產生的文件類型。而且,因為我現在要處理通用的樣板環境,而不是特定於 XML 的 API,所以確保標記匹配、元素和屬性的順序正確以及 XML 實體(例如 <&)正確轉義就成了我的責任。JSP 的核心 out 標記使後面這項工作變得很容易,但是不是所有的樣板技術都提供了這樣的機制。最後,沒有方便的途徑可以在伺服器端根據方案檢驗產生的 XML 文件的正確性,但這畢竟不是要在生產環境中做的事,可以方便地在開發期間處理它。



回到頂端


不用 XML 的響應資料

迄今為止,我介紹的所有技術都用 XML 文件的形式產生伺服器響應。但是,XML 有一些問題。其中一個就是延遲。瀏覽器不能立即解析 XML 文件並產生 DOM 模型,所以這會降低某些 Ajax 元件需要的「迅捷」感,特別是在較慢的機器上解析大型文件的時候更是如此。「現場搜索」就是一個範例,在這種搜索中,當用戶輸入搜索術語時,就會從伺服器提取搜索結果並顯示給用戶。對於現場搜索元件來說,迅速地響應輸入是非常重要的,但是同時它還需要迅速而持續地解析伺服器的響應。

延遲是一個重要的考慮因素,但是避免使用 XML 的最大原因是差勁的用戶端 DOM API。清單 5 顯示了使用跨瀏覽器兼容的方式透過 DOM 得到某個值的時候,通常不得不面對的困難。


清單 5. 在 JavaScript 中導航 XML 響應文件

				
// Find name of first item in customer's last order
var orderHistoryDoc = req.responseXML;

var orders = orderHistoryDoc.getElementsByTagName("order");
var lastOrder = orders[orders.length - 1];

var firstItem = lastOrder.getElementsByTagName("item")[0];
var itemNameElement = firstItem.firstChild;

var itemNameText = itemNameElement.firstChild.data;

當元素中間存在空白時,情況就變得更加複雜,因為每個元素的 firstChild 經常是個空白文件節點。現在有 JavaScript 函式庫可以緩解處理 XML 文件的麻煩。這些函式庫包括 Sarissa (請參閱 參考資料)和 Google-ajaXSLT,這兩個函式庫都把 XPath 功能加入到了大多數瀏覽器中。

但是,想想替代方案還是值得的。除了 responseXML 之外,XMLHttpRequest 物件還提供了名為 responseText 的屬性,這個屬性只是以字符串的方式提供伺服器的響應體。

responseText 屬性

當伺服器需要向使用者端發送非常簡單的值時,responseText 特別方便,它可以避免 XML 導致的帶寬支出和處理支出。例如,簡單的 true/false 響應可以由伺服器以純文件方式傳回,可以是逗號分隔的簡單的名稱或數字列表。但是,一般來說,最好不要在同一個應用程序中把 XML 響應和純文件響應混合使用;保持單一資料格式可以讓程式碼抽像和重用更加簡單。

responseText 與 XML 響應資料結合時也會有用。在只需要從響應文件中提取單一值的場景中,「欺騙性」地把 XML 當作文件字符串,而不把它當作結構化的文件對待,會更方便。例如,清單 6 顯示了如何用正則表達式從顧客的訂單歷史中提取第一筆訂單的日期。不過,這實際是種花招,一般不應當依賴 XML 文件的詞彙表達。


清單 6. 用正則表達式處理 XMLHttpRequest 的 responseText 物件

				
var orderHistoryText = req.responseText;
var matches = orderHistoryText.match(/<date>(.*?)<\/date>/);

var date = matches[1];

在某些情況下,採用即時方式使用 responseText 會比較方便。但是,理想情況下,應當有種途徑,可以用一種能夠讓 JavaScript 輕鬆導航、卻沒有 XML 處理支出的格式表示複雜的結構化資料。幸運的是,確實存在這樣一種格式。



回到頂端


JavaScript 物件表示法

實際上,JavaScript 對象的大部分都由聯合數組、數字索引數組、字符串、數字或者這些類型的巢狀組合而成。因為所有類型都可以用 JavaScript 直接宣告,所以可以在一條語句中靜態地定義物件圖。清單 7 使用 JSON 語法宣告了一個對象,並示範了如何存取這個對象。大括號表示聯合數組(即物件),它的鍵 -值組合由逗號分隔。方括號表示數字索引數組。


清單 7. 用 JSON 在 JavaScript 中直接宣告一個簡單物件

				
var band = {
  name: "The Beatles",
  members: [
    {
      name: "John",
      instruments: ["Vocals","Guitar","Piano"]
    },
    {
      name: "Paul",
      instruments: ["Vocals","Bass","Piano","Guitar"]
    },
    {
      name: "George",
      instruments: ["Guitar","Vocals"]
    },
    {
      name: "Ringo",
      instruments: ["Drums","Vocals"]
    }
  ]
};

// Interrogate the band object
var musician = band.members[3];
alert( musician.name
        + " played " + musician.instruments[0] 
        + " with " + band.name );

既然 JSON 是一個有趣的語言特性,那麼它對 Ajax 有什麼意義呢?妙處在於可以用 JSON 在 Ajax 伺服器響應中透過網路發送 JavaScript 物件圖。這意味著在用戶端可以避免使用笨拙的 DOM API 對 XML 進行導航 —— 只需要分析 JSON 響應,就會立即得到可以存取的 JavaScript 物件圖。但是,首先需要把 JavaBean 變成 JSON。

從 Java 類別產生 JSON

不同 XML 產生技術所具有的優缺點也適用於 JSON 的產生。而且可以證明,存在需要再次使用表示樣板技術的情況。但是,使用 JSON 在理念上更接近於在應用層之間傳遞序列化的對象,而不是建立應用程序狀態的視圖。我將介紹如何用 org.json 這個 Java API 在 Java 類別上建立 toJSONObject() 方法。然後,就可以把 JSONObject 簡單地序列化成 JSON。清單 8 反應了 清單 1 討論的 XML,顯示了 Order 類別的 toJSONObject() 實作。


清單 8. Order 類別的 toJSONObject() 方法實作

				
public JSONObject toJSONObject() {

  JSONObject json = new JSONObject();
  json.put("id",id);
  json.put("cost",getFormattedCost());
  json.put("date",date);

  JSONArray jsonItems = new JSONArray();
  for (Iterator<Item> iter = 
   items.iterator() ; iter.hasNext() ; ) {
    jsonItems.put(iter.next().toJSONObject());
  }
  json.put("items",jsonItems);

  return json;
}

可以看到,org.json API 非常簡單。 JSONObject 代表 JavaScript 物件(即聯合數組),有不同的 put() 方法,方法接受的 String 鍵和值是原生類型、String 類型或其他 JSON 類型。JSONArray 代表索引數組,所以它的 put() 方法只接受一個值。請注意在清單 8 中,建立 jsonItems 數組,然後再用 put() 把它附加到 json 物件上;可以用另外一種方法做這項工作,就是對每個專案呼叫 json.accumulate("items",iter.next().toJSONObject());accumulate() 方法與 put() 類似,區別在於它把值加入到按照鍵進行識別的索引數組。

清單 9 顯示了如何序列化 JSONObject 並把它寫入 servlet 響應。


清單 9. 從 JSONObject 產生序列化的 JSON 響應

				
public void doGet(HttpServletRequest req, HttpServletResponse res) 
  throws java.io.IOException, ServletException {

	String custId = req.getParameter("username");
	Customer customer = getCustomer(custId);

	res.setContentType("application/x-json");
	res.getWriter().print(customer.toJSONObject());
}

可以看到,它實際上什麼也沒有做。在這裡隱式呼叫的 JSONObjecttoString() 方法做了所有工作。請注意,application/x-json 內容類型還有一點不確定 —— 在撰寫這篇文章的時候,關於 JSON 應當屬於什麼 MIME 類型還沒有定論。但是,目前 application/x-json 是合理的選擇。清單 10 顯示了這個 servlet 程式碼的範例響應。


清單 10. Customer bean 的 JSON 表示

				
{
  "orders": [
    {
      "items": [
        {
          "price": "$49.99",
          "description": "512 Megabyte Type 1 CompactFlash card. 
                              Manufactured by Oolong Industries",
          "name": "Oolong 512MB CF Card",
          "id": "i-55768"
        },
        {
          "price": "$299.99",
          "description": "7.2 Megapixel digital camera featuring six 
            shooting modes and 3x optical zoom. Silver.",
          "name": "Fujak Superpix72 Camera",
          "id": "i-74491"
        }
      ],
      "date": "08-26-2005",
      "cost": "$349.98",
      "id": "o-11123"
    }
  ],
  "realname": "James Hyrax",
  "username": "jimmy66"
}

在用戶端使用 JSON

處理的最後一步是把在用戶端把 JSON 資料變成 JavaScript 對象。這可以透過對 eval() 的簡單呼叫實作,這個函數可以即時地解釋包含 JavaScript 表達式的字符串。清單 11 把 JSON 響應轉變成 JavaScript 物件圖,然後執行清單 5 的任務,從顧客的最後一次訂單中得到第一個商品的名稱。


清單 11. 評估 JSON 響應

				
var jsonExpression = "(" + req.responseText + ")";
var customer = eval(jsonExpression);

// Find name of first item in customer's last order
var lastOrder = customer.orders[customer.orders.length-1];
var name = lastOrder.items[0].name;

比較清單 11 和 清單 5 可以發現使用 JSON 的用戶端的優勢。如果在 Ajax 專案中要在用戶端對許多複雜的伺服器響應進行導航,那麼 JSON 可能適合您的需要。JSON 和 XMLHttpRequest 結合還會讓 Ajax 互動看起來更像 RPC 呼叫而不是 SOA 請求,這對應用程序的設計可能會有意義。在下一篇文章中,我要研究的框架,就是明確地為了讓 JavaScript 程式碼對伺服器端物件進行遠端方法呼叫而設計的。

JSON 的不足

JSON 也有它的不足。使用這裡介紹的 JSON 方式,就沒有辦法針對每個請求對對象的序列化進行裁剪,所以不需要的字段可能經常會在網路上發送。另外,加入 toJSONObject() 方法到每個 JavaBean,可伸縮性不太好,雖然用預設和表示法撰寫一個通用的 JavaBean 到 JSON 的序列化器可能很簡單。最後,如果伺服器端程式碼是服務導向的,沒有單獨針對處理 Ajax 客戶請求調整過,那麼由於對 XML 一致的支援,XML 會是更好的選擇。



回到頂端


比較序列化技術

現在已經看到了把 Java 狀態傳輸到 Ajax 用戶端的五種不同技術。我討論了自行手工編碼 XML 序列化、透過程式碼產生的 XML 繫結、透過對應機制的 XML 繫結、基於樣板的 XML 產生以及手工編碼到 JSON 的序列化。每種技術都有自己的優勢和不足,分別適用於不同的應用程序架構。

為了總結每種方式的優勢與不足,表 1 從六個方面進行了粗略的評分:

可伸縮性
描述技術適應大量資料類型的容易程度。對於每個附加類型,編碼和設定工作量是否會增長?
易於整合
評估把技術整合到專案的簡單程度。是否需要更加複雜的建立過程?是否增加了部署的複雜性?
Java 類別 API
描述以指定方式處理伺服器端 Java 對象的容易程度。是可以撰寫普通的 bean,還是不得不處理笨拙的文件表示?
對輸出的控制
描述對類別的序列化表示控制的精確程度。
視圖靈活性
評估從同一組對象是否可以建立不同的、制定的資料序列化。
用戶端資料存取
描述 JavaScript 程式碼處理伺服器響應資料的難易程度。

表 1. 資料產生技術的相對價值
自行撰寫 XML透過程式碼產生的 XML 繫結透過對應的 XML 繫結頁面樣板 XML手工編碼的 JSON 序列化
可伸縮性一般一般
易於整合一般一般
Java 類別 API
對輸出的控制一般
視圖靈活性
用戶端資料存取一般



回到頂端


結論

表 1 中的資料並不表明某項序列化技術比其他的技術好。畢竟,六種標準的相對重要性取決於專案的具體情況。例如,如果要處理數百種資料類型,這時想要的是可伸縮性,那麼程式碼產生可能就是最好的選擇。如果需要為同一資料模型產生多個不同視圖,那麼就應當使用頁面樣板。如果處理的是小規模專案,想降低需要撰寫的 JavaScript 程式碼數量,那麼請考慮 JSON。

希望這篇文章為您提供了選擇適合自己應用程序的序列化技術所需要的信息。請參閱 參考資料 一節,學習關於這裡討論的技術的更多內容。您還應當繼續關注這個系列的下一篇文章,在下一篇文章中,我將介紹如何用直接 Web 遠端(DWR)撰寫 Java Ajax 應用程序。DWR 框架支援從 JavaScript 程式碼中直接呼叫 Java 類別上的方法。換句話說,它替您負責資料序列化的工作,所以您可以在更高的抽像層次上使用 Ajax。



回到頂端


參考資料

學習

取得產品及技術資料
  • Sarissa:一個支援 XPath 的跨瀏覽器的 JavaScript 函式庫。

  • Jakarta Commons Betwixt:一個靈活的基於對應的 XML 繫結庫。

  • JSON:用於 Java 和其他語言的 JavaScript 物件表示法 API。


討論


回到頂端


關於作者

Philip McCarthy 是一位軟體開發顧問,專攻 Java 和 Web 技術。他目前在位於 Bristol 的 HP 實驗室從事 Hewlett Packard 數字媒體平台的工作 。在最近幾年中,Phil 開發了多個採用非同步伺服器通信和 DOM 腳本的富 Web 用戶端。他很高興我們現在有了一個針對它們的名稱。可以透過 Phil 的電子郵件 philmccarthy@gmail.com 與他連絡。




回到頂端


對本文的評價

不甚滿意!(1)
可再加強 (2)
持平 (3)
相當不錯 (4)
受益匪淺!(5)



回到頂端



    關於IBM隱私權條款聯絡我們