首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Axis2 核心技術深度解析:AXIOM XML 文檔模型

     編輯:Java 相關知識

為什麼需要另一種文檔模型?

Apache Axis2 1.1 版本已發布,為長期使用 Apache Web 服務框架的開發者帶來令人振奮的新特性。本系列文章將深入探討 Axis2 的核心創新——AXIOM (AXis Object Model) XML 文檔模型。AXIOM 是 Axis2 性能優於前代 Axis 的關鍵原因之一。本文將介紹 AXIOM 的運作原理、Axis2 各組件如何建構於 AXIOM 之上,以及 AXIOM 與其他 Java 文檔對象模型的性能對比。

文檔模型的困境

處理 XML 時,Java 開發者可選擇多種文檔模型:W3C DOM 各種實現、JDOM、dom4j、XOM 等。各模型在性能、靈活性、標準遵循度上各有優劣。但 Axis2 為何需要新模型?答案在於 SOAP 訊息結構,特別是 SOAP Header 的擴展機制。

SOAP 簡介

SOAP 本質上是 XML 應用負載的簡單包裝。範例 1 展示典型 SOAP 訊息,只有 soapenv 前綴元素屬於 SOAP 定義,大部分內容為應用數據,置於 soapenv:Body 中。

<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/">
 <soapenv:Header/>
 <soapenv:Body>
   <matchQuakes xmlns="https://seismic.sosnoski.com/types">
     <min-date>2001-01-06T11:10:43.446Z</min-date>
     <max-date>2001-10-24T19:49:13.812Z</max-date>
     <min-long>-150.94307</min-long>
     <max-long>-22.594208</max-long>
     <min-lat>-11.44651</min-lat>
     <max-lat>55.089058</max-lat>
   </matchQuakes>
 </soapenv:Body>
</soapenv:Envelope>

SOAP 透過可選的 Header 提供無限制擴展能力。Header 可攜帶各類元數據,不影響應用數據處理。WS-* 系列標準即利用 Header 實現功能,如範例 2 所示的 WS-Addressing 資訊,使訊息能跨協議傳輸、支援存儲轉發。

<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/"
 xmlns:wsa="https://www.w3.org/2005/08/addressing">
 <soapenv:Header>
   <wsa:To>https://localhost:8800/axis2/services/SeisAxis2XBean</wsa:To>
   <wsa:ReplyTo>
     <wsa:Address>https://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
   </wsa:ReplyTo>
   <wsa:MessageID>urn:uuid:97AE2B17231A8584D811537402403691</wsa:MessageID>
 </soapenv:Header>
 <soapenv:Body>...</soapenv:Body>
</soapenv:Envelope>

文檔模型面臨的兩難

SOAP Header 允許任意元數據,框架必須能處理任意 XML,文檔模型恰擅長此道。但對於應用數據交換,數據綁定(Data Binding)將 XML 轉為數據對象,更方便、高效。理想方案是同時使用兩種技術:Body 用數據綁定,Header 用文檔模型。傳統文檔模型卻要求處理整個文檔或完整子樹,無法只處理文檔選定部分。

以拉式解析構建 AXIOM 樹

Axis2 另一大改進是採用拉式 StAX 解析器,取代 Axis 的推式 SAX 解析器。推式由解析器控制流程,拉式則由應用程式主動拉取所需部分。對於 SOAP 這類包含邏輯獨立部分的 XML,拉式更具優勢:處理某部分代碼只解析該部分,其餘交由解析器續處理。

AXIOM 建構於 StAX 之上,提供按需擴展的虛擬文檔模型。僅構建客戶端請求的樹結構表示。元素級運作:解析器報告元素開始標記時創建元素表示,初始僅為保存解析器引用的殼。應用程式需獲取內容細節時,透過 OMContainer.getChildren() 等方法請求,解析器才構建子內容。因解析器按文檔順序傳遞數據,按需構造要求靈活處理:多個不完整元素始終位於樹右側直線上,隨請求逐漸展開。

使用 AXIOM

AXIOM API 與其他文檔模型有相似之處,但因按需構建特性而獨特。訪問方法基於 java.util.Iterator,導航用 OMNode.getNextOMSibling()、getPreviousOMSibling(),符合按需構建邏輯:可移至第一個子元素而無需先處理所有子元素。

AXIOM 使用接口定義 API,提供多種實現:org.apache.axiom.om.impl.dom 同時支援 AXIOM 和 DOM 接口;org.apache.axiom.om.impl.llom 基於鏈表實現;org.apache.axiom.soap 專門處理 SOAP 訊息。

實際應用範例

範例 3 展示解析輸入流為 AXIOM 文檔:

import org.apache.axiom.om.*;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory;
...
private XMLInputFactory m_parserFactory = XMLInputFactory.newInstance();
private OMFactory m_factory = new OMLinkedListImplFactory();
...
protected Object build(InputStream in) {
  Object doc = null;
  try {
    XMLStreamReader reader = m_parserFactory.createXMLStreamReader(in);
    StAXOMBuilder builder = new StAXOMBuilder(m_factory, reader);
    doc = builder.getDocument();
  } catch (Exception ex) { ... }
  return doc;
}

代碼僅創建 StAX 解析器和基本文檔結構,解析器定位於根元素,後續按需構建。也可用 SAXOMBuilder 基於 SAX 構建,但無法享受按需構造優勢。

範例 4 遍歷文檔累計摘要資訊(元素計數、屬性值長度、文本內容長度):

protected void walkElement(OMElement element, DocumentSummary summary) {
  for (Iterator iter = element.getAllAttributes(); iter.hasNext();) {
    OMAttribute attr = (OMAttribute)iter.next();
    summary.addAttribute(attr.getAttributeValue().length());
  }
  for (Iterator iter = element.getChildren(); iter.hasNext();) {
    OMNode child = (OMNode)iter.next();
    int type = child.getType();
    if (type == OMNode.TEXT_NODE) {
      summary.addContent(((OMText)child).getText().length());
    } else if (type == OMNode.ELEMENT_NODE) {
      summary.addElements(1);
      walkElement((OMElement)child, summary);
    }
  }
}
protected void walk(Object doc, DocumentSummary summary) {
  summary.addElements(1);
  walkElement(((OMDocument)doc).getOMDocumentElement(), summary);
}

範例 5 將文檔序列化輸出:

protected void output(Object doc, OutputStream out) {
  try {
    ((OMDocument)doc).serializeAndConsume(out);
  } catch (Exception ex) { ... }
}

AXIOM 提供修改文檔基本方法(如 OMElement.setText()),從頭創建文檔則透過工廠創建組件實例。

AXIOM 中的 MTOM/XOP 支援

AXIOM 內建支援 W3C XOP 和 MTOM 標準,用於 SOAP 附件傳輸。XOP 以 Base64 編碼二進制數據,透過 xop:Include 元素引用外部實體(URI),減小文檔體積、避免編解碼開銷。MTOM 將 XOP 應用於 SOAP,定義 MIME Multipart/Related 封裝,支援 HTTP 傳輸。

AXIOM 透過 OMText 介面及實現支援 XOP/MTOM。OMText 以 DataHandler 表示二進制數據,含「優化」旗標指示是否用 XOP 處理。OMTextImpl 添加 MTOM 相容內容 ID。

範例 6 創建 XOP/MTOM 訊息:

public OMElement matchQuakes(OMElement req) {
  Query query = new Query();
  Iterator iter = req.getChildElements();
  try {
    Response response = QuakeBase.getInstance().handleQuery(query);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(response);
    byte[] byts = bos.toByteArray();
    ByteArrayDataSource ds = new ByteArrayDataSource(byts);
    OMFactory fac = OMAbstractFactory.getOMFactory();
    OMNamespace ns = fac.createOMNamespace("https://seismic.sosnoski.com/types", "qk");
    OMElement resp = fac.createOMElement("response", ns);
    OMText data = fac.createOMText(new DataHandler(ds), true);
    resp.addChild(data);
    return resp;
  } catch (Exception e) { ... }
  return null;
}

需在 Axis2 配置中啟用 <parameter name="enableMTOM">true</parameter>。範例 7 展示啟用與未啟用 XOP/MTOM 的回應差異。

數據綁定掛鉤

開發者習慣用 Java 對象而非 XML。Axis2 重新設計支援多種數據綁定框架作為「插件」。透過擴展 WSDL2Java 工具,生成存根代碼在 OMElement 和 Java 對象間轉換。入站時,XML 負載以 OMElement 形式獲取,數據綁定框架處理元素數據(可直接用 XMLStreamReader)。出站時,AXIOM 用 OMDataSource 包裝數據綁定轉換,按需提供數據,避免構建完整 XML 表示。

性能分析

測試環境:Compaq 筆記本,1.6GHz AMD Turion,1.5GB RAM,Mandriva Linux,Sun JVM 1.5.0_07。對比 AXIOM 1.0、dom4j 1.6.1、JDOM 1.0、Xerces2 2.7.0、XOM (Nux 1.6),均用 Woodstox StAX 2.9.3 解析器。測試三種 SOAP 文檔:「quakes」(18KB)、「persons」(202KB)、「soaps」(19KB,30個小訊息)。

圖1:構建和展開文檔時間

圖1:構建並完整展開文檔的平均時間。除 Xerces2 外,AXIOM 比其他模型略慢。

圖2:寫入文檔時間

圖2:寫入輸出流平均時間。Xerces2 最快,AXIOM 最差,尤其小文檔。

圖3:文檔內存大小

圖3:內存佔用。dom4j 最優,AXIOM 明顯較大,部分因保存解析器引用,部分因對象本身較大。

圖4:初始文檔構建

圖4:初始構建時間(不展開)。AXIOM 顯著更快,大文檔甚至難以測量。若只需處理文檔部分(如按順序的首部),AXIOM 性能優異。

結語

AXIOM 的按需構建思想創新,完整展開時性能不如傳統模型(尤其小文檔),但針對 Web 服務處理靈活性足以彌補。下一篇將探討 Axis2 如何支援不同數據綁定框架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved