月蝕傳說(shuō)

          浮躁讓人失去理智
          posts - 25, comments - 101, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理

          讓Axis支持EMF模型

          Posted on 2006-08-30 18:23 Dart 閱讀(2020) 評(píng)論(5)  編輯  收藏 所屬分類: SCA 、EMF

          Axis Java 陣營(yíng)中最常用的一個(gè) Web 服務(wù)組件。通過(guò)一些配置就可以利用它去生成、部署 Web 服務(wù)。


          但是目前
          Axis 只支持 XMLBean Castor JavaBean 復(fù)雜類型數(shù)據(jù)結(jié)構(gòu),于是在使用的時(shí)候,特別是一些比較高級(jí)的 Web 服務(wù)使用的時(shí)候,復(fù)雜數(shù)據(jù)類型就會(huì)受到一定的限制。這里我給出一個(gè)關(guān)于如何讓 Axis 支持 EMF 模型的例子,希望能借此能給讀者一些提示。在這里我假設(shè)讀者都使用過(guò) Axis ,如果需要獲得更多的 Axis 信息,請(qǐng)點(diǎn)這里。關(guān)于EMF的信息可以從這里獲得。相關(guān)代碼下載


          1.??????
          類型映射

          Axis Server-config.wsdd 文件中,我們需要自己定義部署的服務(wù)的一些配置信息,其中有一個(gè)名為 typeMapping 的元素,該元素就是配置如何映射復(fù)雜類型數(shù)據(jù)結(jié)構(gòu)的一些信息。 typeMapping 元素具有以下屬性:


          1)?
          Deserializer? 反序列化 XML 到我們所需要對(duì)象的 DeserializerFactory

          ???2)? Serializer???? 序列化對(duì)象到 XML SerializerFactory

          ???3)? encodingStyle? 編碼類型,我一般設(shè)為空

          ???4)? type??????????? 需要映射的復(fù)雜類型數(shù)據(jù)對(duì)象類

          ???5)? qname?????????? 數(shù)據(jù)類型在 XML 中對(duì)應(yīng)的 QName (命名空間加上元素的名稱)

          ?

          當(dāng)我們?cè)L問(wèn)某個(gè) Web 服務(wù)時(shí),如果返回類型,或者是我們的客戶端調(diào)用代碼中涉及到了復(fù)雜類型, Axis 會(huì)去查詢我們 typeMapping 中定義好的并且和該復(fù)雜類型匹配的 DeserializerFactory 或者 SerializerFactory 類,然后返回對(duì)應(yīng)的 Deserializer Serializer 類,通過(guò)該類序列化或者反序列化這個(gè)復(fù)雜類型。所以如果我們所定義的復(fù)雜類型并非 Castor 、 JavaBean XMLBean 的時(shí)候,就需要我們自己去創(chuàng)建 DeserializerFactory SerializerFactory 。


          2
          DeserializerFactory Deserializer

          反序列化工廠是用戶將 XML 轉(zhuǎn)成 Java 對(duì)象的工廠,它維護(hù)了一個(gè) Deserializer 對(duì)象,該對(duì)象才是真正去做反序列化工作的類。

          我們現(xiàn)在創(chuàng)建自己的 Deserializer 類以及 Deserializer 工廠類:

          public ? class ?EMFDeserializerFactory? extends ?BeanDeserializerFactory?{

          ??
          public
          ?EMFDeserializerFactory?(Class?javaType,?QName?xmlType)?{

          ?????????
          super
          (javaType,?xmlType);

          ?????????deserClass?
          =??EMFDeserializer.class
          ;

          ??}

          ?
          public ?Deserializer?getDeserializerAs(String?mechanismType)? throws
          ?JAXRPCException?{

          ?????????
          return ? new
          ?EMFDeserializer(javaType,xmlType);

          ?}
          }

          ?

          工廠類的實(shí)現(xiàn)比較簡(jiǎn)單,我們先繼承 BeanDeserializerFactory 類,然后復(fù)寫(xiě)它的 getDeserializerAs 方法,返回相應(yīng)的 Deserializer 類即可。

          ?

          public ? class ?EMFDeserializer? extends ?DeserializerImpl?{

          ???????
          private ?Object?sdoValue? = ? null ;

          ???????
          private ?Class?valueVlazz? = ? null ;

          ???????
          public ?EMFDeserializer(Class?arg0,?QName?arg1)?{

          ??????????????valueVlazz?
          = ?arg0;

          ???????}

          ???????
          public ? void ?onEndElement(String?namespace,?String?localName,

          ?????????????????????DeserializationContext?context)?
          throws ?SAXException?{
          ???????????.
          ???????}
          ?}


          EMFDeserialize
          的工作就是將 XML 文檔轉(zhuǎn)成 EMF 模型。

          我們繼承 DeserializeImpl 類,然后復(fù)寫(xiě)它的 onEndElement 方法。


          public ? class ?EMFDeserializer? extends ?DeserializerImpl?{

          ???????
          public ? void ?onEndElement(String?namespace,?String?localName,

          ?????????????????????DeserializationContext?context)?
          throws ?SAXException?{

          ??????????????…….

          }

          }



          onEndElement 方法中的參數(shù)有一個(gè) DeserializationContext 對(duì)象,我們可以通過(guò)它獲得 XML 文檔片段:


          Document?doc? = ?context.getCurElement().getAsDocument();



          Document 就是得到的 XML 片段。


          然后我們通過(guò)
          EMF 提供的 Resource 對(duì)象將 XML 文檔進(jìn)行反序列化(這里我自己寫(xiě)了一個(gè)創(chuàng)建 XMLResourceImpl 的工廠類,讀者可以在文章后面下載代碼):


          org.apache.xml.serialize.DOMSerializerImpl?s1? = ?
          ???? new
          ?org.apache.xml.serialize.DOMSerializerImpl();
          String?ddd?
          =
          ?s1.writeToString(doc);

          Resource?resource?
          =
          ?GenaralEObjectXMLResourceFactory.getInstance()

          ???????????????????????????????????.createResource(
          null
          );

          resource.load(
          new
          ?ByteArrayInputStream(ddd.getBytes()),

          ???????????????????????????????????Collections.EMPTY_MAP);



          先將
          Document 轉(zhuǎn)成 String ,然后通過(guò) ByteArrayInputStream 傳給 resource,resource load 后會(huì)生成對(duì)應(yīng)的數(shù)據(jù)對(duì)象,并且我們可以通過(guò) resource 獲得:


          sdoValue? = ?resource.getContents().get( 0 );

          value?
          =
          ?sdoValue;



          這里需要注意的是,如果我們生成的
          EMF 模型是通過(guò) XSD 來(lái)生成的,那反序列化后得到的應(yīng)該是一個(gè) DocumentRoot 對(duì)象,該對(duì)象可能并不是我們想得到的,比如:


          <? xml?version=””?encoding=”UTF-8” ?>

          < student? name =”me”/>



          得到的對(duì)象并是不
          Student 對(duì)象,而是一個(gè) DocumentRoot ,而 Student 對(duì)象是包含在 DocuementRoot 對(duì)象的子對(duì)象中。

          但是如果是直接通過(guò) Ecore 模型生成的則不會(huì)有 DocumentRoot 對(duì)象。這里如何去判斷得到的對(duì)象是不是 DocumentRoot 需要讀者進(jìn)一步去看看 EMF ,這里我沒(méi)有給出通用的手段解決,只是根據(jù)我本身程序的需求去獲得的:


          if (sdoValue? instanceof ?EObject){
          ????List?contents?
          =
          ?((EObject)sdoValue).eContents();
          ?? ?
          for ?(Iterator?iter? =
          ?contents.iterator();?iter??.hasNext();)?{

          ?????????????Object?element?
          =
          ?(Object)?iter.next();

          ???????????
          if
          (valueVlazz.isInstance(element)){

          ??????????????????????value?
          =
          ?element;

          ??????????????????????
          break
          ;

          ????????????}

          ????}

          ?}



          這里需要注意,對(duì)象
          value 并不是 EMFDeserializer 自己定義的字段,而是 DeserializerImpl 的字段,該字段就是 Axis 反序列化后的對(duì)象值引用字段。


          3.???
          Serializer SerializerFactory


          SerializerFactory
          的工作和 DeserializerFactory 工作類似,返回一個(gè) Serializer 對(duì)象,它是真正去將對(duì)象序列化成 XML 的類。

          SerializerFactory 比較簡(jiǎn)單,這里就不詳細(xì)介紹了:


          public ? class ?EMFSerializerFactory? extends ?BaseSerializerFactory?{
          ?????????
          public
          ?EMFSerializerFactory(Class?javaType,?QName?xmlType)?{

          ???????????????
          super (EMFSerializer. class
          ,?xmlType,?javaType);

          ???????}
          }

          ?

          Serializer 類需要繼承 Serializer 接口:


          public ? class ?EMFSerializer? implements ?Serializer{
          ???????
          protected
          ?Class?javaType;

          ????????
          protected
          ?QName?xmlType;

          ????????
          public
          ?SDOSerializer(Class?javaType,?QName?xmlType)?{

          ??????????????
          this .javaType? =
          ?javaType;

          ??????????????
          this .xmlType? =
          ?xmlType;

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

          ?????????????????????SerializationContext?context)?
          throws
          ?IOException?{

          ???????????..
          ???????}???????
          ???????
          public ?Element?writeSchema(Class?javaType,?Types?types)? throws
          ?Exception?{

          ?????????????
          return ? null
          ;

          ???????}
          ???????
          public
          ?String?getMechanismType()?{
          ??????????????
          return
          ?Constants.AXIS_SAX;
          ???????}
          }


          我們需要實(shí)現(xiàn)三個(gè)方法:


          1)?
          serialize

          ???2)? getMechanismType

          ???3)? writeSchema


          writeSchema
          方法需要返回一個(gè) XML Schema Element 對(duì)象,該 XML Schema 是指我們所用的 EMF 模型對(duì)應(yīng)的 XML Schema ,我采用的 EcoreXMLSchemaBuilder 類就可以將 EPackage 對(duì)象轉(zhuǎn)換成為一個(gè) Schema Element 。不過(guò)在這里我發(fā)現(xiàn)好像 Axis 對(duì)這個(gè)方法并不是說(shuō)非用不可,我也就沒(méi)有實(shí)現(xiàn),直接返回的是 NULL


          getMechanismType
          方法很簡(jiǎn)單

          public ?String?getMechanismType()?{

          ???
          return
          ?Constants.AXIS_SAX;

          }



          這樣就可以了

          ?

          最重要的是 serialize 方法,這個(gè)方法就是將對(duì)象進(jìn)行序列化的方法:

          ?

          public ? void ?serialize(QName?name,?Attributes?attributes,?Object?value,
          ?????????????????????SerializationContext?context)?
          throws
          ?IOException?{

          ??????????????…..
          }

          ?

          首先要將傳入的 value 序列化成一個(gè) XML 文檔:

          ?

          EPackage?ePackage? = ?((EObject)?value).eClass().getEPackage();

          ?????????????????????String?targetURI?
          =
          ?ePackage.getNsURI();

          ?????????????????????Registry.INSTANCE.put(targetURI,ePackage);

          ?????????????????????Resource?resource?
          = ?GenaralEObjectXMLResourceFactory.getInstance().createResource( null
          );

          ?????????????????????resource.getContents().add(value);

          ?????????????????????ByteArrayOutputStream?stream?
          = ? new
          ?ByteArrayOutputStream();

          ?????????????????????resource.save(stream,?Collections.EMPTY_MAP);

          ?

          我們將序列化后的 XML 存放到了 stream 流中,現(xiàn)在我們需要將這段 XML 寫(xiě)到 SerializationContext 對(duì)象中:


          context.setWriteXMLType( null );

          ?context.startElement(name,attributes);

          ??DOMParser?parser?
          = ? new
          ?DOMParser();

          InputSource?inputSource?
          = ? new
          ?InputSource();

          ??inputSource.setByteStream(
          new
          ?ByteArrayInputStream(stream.toByteArray()));

          ??parser.parse(inputSource);
          ??context.writeDOMElement(parser.getDocument().getDocumentElement());
          ?????????????????????????????????????????????????????context.endElement();

          ?

          這樣我們就完成了對(duì)對(duì)象的序列化。

          ?

          4. 修改 wsdd 文件


          當(dāng)我們使用
          Axis 提供的 WSDL2Java 工具類時(shí), Axis 會(huì)自動(dòng)給我們生成一個(gè) wsdd 文件,而且當(dāng)它發(fā)現(xiàn)定義的 Operation 中涉及到了復(fù)雜類型數(shù)據(jù), Axis 會(huì)自動(dòng)加上 typeMapping 元素,但是它默認(rèn)給這個(gè)元素上定義的 Deserializer , Serializer 是針對(duì) JavaBean 的,所以如果我們的類是是 EMF ,只要將 typeMapping 的類型改成 EMFSerializerFactory 以及 EMFDeserializerFactory 就可以了。


          5.
          總結(jié)


          上面是小弟的一點(diǎn)愚見(jiàn),請(qǐng)各位看官多提意見(jiàn)


          評(píng)論

          # re: 讓Axis支持EMF模型  回復(fù)  更多評(píng)論   

          2006-09-18 12:21 by 化工
          樓主說(shuō)的確實(shí)對(duì)我很有用,多謝了!@_@~~

          # re: 讓Axis支持EMF模型  回復(fù)  更多評(píng)論   

          2008-02-27 20:03 by zyymmm
          對(duì)我很有幫助啊,不過(guò)對(duì)于我這樣的菜鳥(niǎo)來(lái)說(shuō),代碼過(guò)于省略了,看著費(fèi)勁

          # re: 讓Axis支持EMF模型  回復(fù)  更多評(píng)論   

          2008-02-27 20:05 by zyymmm
          還有啊,我迫切需要本篇文章涉及到的全部代碼,文章中說(shuō)有連接可以下載,但是我沒(méi)發(fā)現(xiàn)啊。
          樓主能不能郵寄一份給我呀,萬(wàn)分感謝。

          我的郵箱: zyymmm@163.com

          # re: 讓Axis支持EMF模型  回復(fù)  更多評(píng)論   

          2008-02-28 10:48 by 趙宇明
          樓主,我迫切需要得到本文中所涉及到的整套代碼~
          程序的主干是描述清楚了,但是有些地方?jīng)]有寫(xiě)全,所以我就搞不懂了。

          拜托了,拉兄弟一把,我的email: zyymmm@163.com

          # re: 讓Axis支持EMF模型  回復(fù)  更多評(píng)論   

          2008-02-28 11:36 by 趙宇明
          哦,樓主,我發(fā)現(xiàn)下載鏈接了,不好意思。
          方便的時(shí)候,能否在QQ或MSN上加我?真的非常希望能認(rèn)識(shí)您這樣的高手!非常真誠(chéng)的,^_^
          主站蜘蛛池模板: 绥芬河市| 应城市| 瑞金市| 石景山区| 宜都市| 新余市| 阿拉善盟| 楚雄市| 泽州县| 集安市| 五莲县| 奉节县| 临洮县| 芒康县| 鄂托克旗| 南安市| 保康县| 蒙城县| 奉化市| 高碑店市| 靖西县| 钟祥市| 昌乐县| 兴国县| 沽源县| 泸溪县| 达拉特旗| 英吉沙县| 许昌市| 奈曼旗| 黄平县| 游戏| 如东县| 沐川县| 墨脱县| 睢宁县| 云梦县| 黄梅县| 栾城县| 阿拉尔市| 宿迁市|