程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Axis序列化/反序列化器開發指南

Axis序列化/反序列化器開發指南

編輯:關於JAVA

前言

  

  Axis是Apache組織推出的SOAP引擎,Axis項目是apache組織著名的SOAP項目的後繼項目。Axis為開發者提供了大量的序列化/反序列化器,能夠基本滿足大部分應用。但在某些情況下,對特定的對象,現有的序列化/反序列化器不能勝任,於是只有開發人員自己實現專用於此對象的序列化/反序列化器插入到Axis中來完成序列化工作。考慮到Web Service是一門新興技術,中文資料大多是泛泛的講解,關於序列化/反序列化器的開發鮮有較為深入的介紹,本文提供一份較為完整的開發指南,並提供了一個十分有用的實現,即序列化JDOM模型的Element,使其可以通過Web 服務在網絡上傳輸,我想這一擴展是許多采用JDOM作為XML解析工具的開發人員都夢寐以求的功能。通過本文的介紹和實例,希望能起到拋磚引玉的作用,讀者在閱讀完本文之後可以輕松的實現針對於任何非符合BEAN規范的對象的序列化/反序列化器。

  

  本文所面對的讀者需要有一定的使用Axis做Web服務開發的開發經驗,因此關於如何Axis的基礎知識並不在本文的介紹范圍,如果讀者對此感興趣,可以參考本文最後的參考資料部分,去相應的網站進行學習。

  

  序列化/反序列化器簡介

  

  序列化/反序列化器在英文中的對應翻譯是Serializer/Deserializer,一個序列化器的功能是遵循一定的映射規則和編碼風格,將一種類型的JAVA對象通過某種特定的機制,轉換成為XML描述的形式;反序列化器的功能是序列化器所做工作的逆操作,兩者相輔相成,成對出現。Axis中的序列化/反序列化器采用設計范式中的工廠模式,每一個Serializer唯一對應一個SerializerFactory;每一個Deserializer唯一對應一個DeserializerFactory。一種類型的JAVA對象具體要采用哪個序列化/反序列化器需要在提供Web服務的服務器和調用Web服務的客戶端分別配置,關於這一部分如何配置,我將在本文後面的內容中進行詳細介紹。Axis已經為開發者提供了豐富的序列化/反序列化器,對於java的基本數據類型,絕大部分常用的容器類(比如數組類型,Vector類型等)都提供了實現,特別是提供了對W3C的DOM對象(比如Document, Element等)和符合Bean規范的JAVA對象提供了功能完善的序列化/反序列化器,因此我們在需要的時候只要在配置文件中配置一下就可以直接使用。如果對象中包含其它類型的對象,比如Vector中包含一組Bean對象,Axis會自動疊代的調用序列化器,最終拼裝成唯一的XML表述。在還原成Java對象時,也遵循這樣的疊代操作逆向進行。關於Axis到底內置了哪些序列化/反序列化器,您可以參照Axis的API文檔中包org.apache.axis.encoding.ser下的類的名稱"望文生義"的了解一下,在以後的開發中做到心中有數。但對於一些特殊類型的對象(其實我們自己開發的很大一部分類都是這種特殊類型的對象,很少有絕對符合Bean規范的),需要通過Web服務進行傳遞,我們不得不開發自己的序列化/反序列化器。

  

  開發篇

  

  開發自己的序列化/反序列化器是一個激動人心的工作,但是卻並不復雜,需要做的事情包括實現名成為org.apache.axis.encoding的包中的SerializerFactory,Serializer,DeserializerFactory和Deserializer這四個接口。下面我將結合一個實例來講解序列化/反序列化器的開發方法,希望讀者能夠一邊參看本文提供的源代碼一邊學習。

  

  JDOM作為一款比較"另類"的XML解析工具(因為它不符合W3C的DOM模型,自己另立一套)默默地占領著Java世界裡的xml解析器的半壁江山,由於其簡潔的設計和方便靈活的API調用,已經漸漸成為了許多開發人員在進行XML開發的首選。但是Axis是建立在W3C的DOM模型的基礎之上,師出名們正派,自然不屑與JDOM為伍。因此當開發人員想將自己已經寫好的基於JDOM的應用模塊采用Web服務的方式發布的時候,不可避免的會遇到如何將JDOM模型下的對象如Document, Element等序列化的問題。在軟件工程師不會自己擴展Axis的序列化/反序列化器的時候,我們只能有兩個辦法達到這個目的,第一個就是更改以前應用模塊內的API設計,使暴露的入口參數和返回值參數都是W3C的對象類型,但這種做法並不現實,因為這一應用模塊往往不是獨立存在,牽一發將動全身,導致舊有系統架構的崩塌;另一種做法就是為這個模塊做一個代理類,它做的工作就對外接收或返回DOM模型的對象,對內轉換成JDOM模型的對象,然後轉發給應用模塊,繁瑣且效率低下。當我們向Axis注入了針對於JDOM模型的序列化/反序列化器後,這一工作便可以由Axis代勞了。下面我們將逐個開發這四個類:

  

  JDomElementSerializerFactory

  

  JDomElementSerializerFactory是一個工廠類,需要通過某種機制注冊到Axis引擎(具體方法見下面"服務器端應用篇");Axis通過調用它,來實例化JDomElementSerializer。Axis 提供了BaseSerializerFactory,這個類是一個抽象類,並實現其中包含了一些可重用的代碼。我們自己開發的工廠類只需簡單繼承這個類就可以。構造函數中需要調用父類的構造函數將序列器類下面是它的源代碼:

  

  package org.apache.axis.encoding.ser;

  

  public class JDomElementSerializerFactory

  extends BaseSerializerFactory {

  

  public JDomElementSerializerFactory() {

  super(JDomElementSerializer.class);

  }

  }

  

  JDomElementSerializer

  

  JDomElementSerializer實現org.apache.axis.encoding.Serializer接口,其核心API是serialize(),我們需要在這個方法的內部完成對JDOM模型的Element的序列化工作,序列化的結果要保存在入口參數傳入的序列化上下文對象(SerializationContext)中:

  

  public void serialize(QName name, Attributes attributes, Object value,

  SerializationContext context) throws Java.io.IOException {

  

  if (!(value instanceof Element))

  throw new IOException(

  Messages.getMessage("cant Serialize Object"));

  

  //獲取符合JDOM的Element對象

  Element root=(Element)value;

  

  //輸出到StringWriter

  XMLOutputter outputter=new XMLOutputter();//創建一個JDOM的XML輸出器

  StringWriter sw=new StringWriter();

  outputter.output(root,sw);

  

  //用支持W3C的DOM模型的Xerces解析器解析文本流

  DOMParser parser=new DOMParser();//創建一個DOM的XML解析器

  try {

  parser.parse(new org.XML.sax.InputSource(

  new Java.io.StringReader(sw.toString())));

  }catch (Exception ex) {

  throw new Java.io.IOException("序列化時產生錯誤");

  }

  

  //獲取符合DOM模型的Element對象

  org.w3c.dom.Element w3c_root =

  parser.getDocument().getDocumentElement();

  

  //放入序列化上下文對象中

  context.startElement(name, attributes);

  context.writeDOMElement(w3c_root);

  context.endElement();

  }

  

  JDomElementDeserializerFactory

  

  反序列化器的工廠類同序列化器的工廠類一樣的設計,在此不在贅述。代碼:

  

  package org.apache.axis.encoding.ser;

  

  public class JDomElementDeserializerFactory

  extends BaseDeserializerFactory {

  

  public JDomElementDeserializerFactory() {

  super(JDomElementDeserializer.class);

  }

  

  }

  

  JDomElementDeserializer

  

  用過SAX解析XML的讀者,對反序列化的實現比較容易理解,反序列化也采用了消息觸發的機制,我們只需繼承org.apache.axis.encoding.DeserializerImpl類,並覆蓋其中的onEndElement方法:

  

  /**

  * 在元素結束觸發反序列化的方法

  * @param namespace String 命名空間

  * @param localName String 本地名稱

  * @param context DeserializationContext 反序列化上下文

  * @throws SAXException

  */

  public void onEndElement(String namespace, String localName,

  DeserializationContext context) throws SAXException {

  

  try {

  //從反序列化上下文對象中獲取原始的消息元素

  MessageElement msgElem = context.getCurElement();

  if (msgElem != null) {

  MessageContext messageContext = context.getMessageContext();

  Boolean currentElement = (Boolean) messageContext.getProperty(

  DESERIALIZE_CURRENT_ELEMENT);

  

  //如果當前的消息元素本身需要反序列化

  if (currentElement != null && currentElement.booleanValue()) {

  org.w3c.dom.Element element = msgElem.getAsDOM();

  org.jdom.input.DOMBuilder db=new org.jdom.input.DOMBuilder();

  value=db.build(element);

  messageContext.setProperty(DESERIALIZE_CURRENT_ELEMENT,

  Boolean.FALSE);

  return;

  }

  

  //反序列化消息元素中的消息體

  Java.util.ArrayList children = msgElem.getChildren();

  if (children != null) {

  

  //取得消息體

  msgElem = (MessageElement) children.get(0);

  if (msgElem != null) {

  org.w3c.dom.Element ret = msgElem.getAsDOM();

  org.jdom.input.DOMBuilder db=new org.jdom.input.DOMBuilder();

  

  //用DOMBuilder將DOM模型的Element,轉換成JDOM模型的Element

  value=db.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved