<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    月蝕傳說

    浮躁讓人失去理智
    posts - 25, comments - 101, trackbacks - 0, articles - 0
      BlogJava :: 首頁 ::  :: 聯系 :: 聚合  :: 管理

    讓Axis支持EMF模型

    Posted on 2006-08-30 18:23 Dart 閱讀(2010) 評論(5)  編輯  收藏 所屬分類: SCAEMF

    Axis Java 陣營中最常用的一個 Web 服務組件。通過一些配置就可以利用它去生成、部署 Web 服務。


    但是目前
    Axis 只支持 XMLBean Castor JavaBean 復雜類型數據結構,于是在使用的時候,特別是一些比較高級的 Web 服務使用的時候,復雜數據類型就會受到一定的限制。這里我給出一個關于如何讓 Axis 支持 EMF 模型的例子,希望能借此能給讀者一些提示。在這里我假設讀者都使用過 Axis ,如果需要獲得更多的 Axis 信息,請點這里。關于EMF的信息可以從這里獲得。相關代碼下載


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

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


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

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

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

    ???4)? type??????????? 需要映射的復雜類型數據對象類

    ???5)? qname?????????? 數據類型在 XML 中對應的 QName (命名空間加上元素的名稱)

    ?

    當我們訪問某個 Web 服務時,如果返回類型,或者是我們的客戶端調用代碼中涉及到了復雜類型, Axis 會去查詢我們 typeMapping 中定義好的并且和該復雜類型匹配的 DeserializerFactory 或者 SerializerFactory 類,然后返回對應的 Deserializer Serializer 類,通過該類序列化或者反序列化這個復雜類型。所以如果我們所定義的復雜類型并非 Castor JavaBean XMLBean 的時候,就需要我們自己去創建 DeserializerFactory SerializerFactory


    2
    DeserializerFactory Deserializer

    反序列化工廠是用戶將 XML 轉成 Java 對象的工廠,它維護了一個 Deserializer 對象,該對象才是真正去做反序列化工作的類。

    我們現在創建自己的 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);

    ?}
    }

    ?

    工廠類的實現比較簡單,我們先繼承 BeanDeserializerFactory 類,然后復寫它的 getDeserializerAs 方法,返回相應的 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 文檔轉成 EMF 模型。

    我們繼承 DeserializeImpl 類,然后復寫它的 onEndElement 方法。


    public ? class ?EMFDeserializer? extends ?DeserializerImpl?{

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

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

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

    }

    }



    onEndElement 方法中的參數有一個 DeserializationContext 對象,我們可以通過它獲得 XML 文檔片段:


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



    Document 就是得到的 XML 片段。


    然后我們通過
    EMF 提供的 Resource 對象將 XML 文檔進行反序列化(這里我自己寫了一個創建 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 轉成 String ,然后通過 ByteArrayInputStream 傳給 resource,resource load 后會生成對應的數據對象,并且我們可以通過 resource 獲得:


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

    value?
    =
    ?sdoValue;



    這里需要注意的是,如果我們生成的
    EMF 模型是通過 XSD 來生成的,那反序列化后得到的應該是一個 DocumentRoot 對象,該對象可能并不是我們想得到的,比如:


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

    < student? name =”me”/>



    得到的對象并是不
    Student 對象,而是一個 DocumentRoot ,而 Student 對象是包含在 DocuementRoot 對象的子對象中。

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


    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
    ;

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

    ????}

    ?}



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


    3.???
    Serializer SerializerFactory


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

    SerializerFactory 比較簡單,這里就不詳細介紹了:


    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;
    ???????}
    }


    我們需要實現三個方法:


    1)?
    serialize

    ???2)? getMechanismType

    ???3)? writeSchema


    writeSchema
    方法需要返回一個 XML Schema Element 對象,該 XML Schema 是指我們所用的 EMF 模型對應的 XML Schema ,我采用的 EcoreXMLSchemaBuilder 類就可以將 EPackage 對象轉換成為一個 Schema Element 。不過在這里我發現好像 Axis 對這個方法并不是說非用不可,我也就沒有實現,直接返回的是 NULL


    getMechanismType
    方法很簡單

    public ?String?getMechanismType()?{

    ???
    return
    ?Constants.AXIS_SAX;

    }



    這樣就可以了

    ?

    最重要的是 serialize 方法,這個方法就是將對象進行序列化的方法:

    ?

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

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

    ?

    首先要將傳入的 value 序列化成一個 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 流中,現在我們需要將這段 XML 寫到 SerializationContext 對象中:


    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();

    ?

    這樣我們就完成了對對象的序列化。

    ?

    4. 修改 wsdd 文件


    當我們使用
    Axis 提供的 WSDL2Java 工具類時, Axis 會自動給我們生成一個 wsdd 文件,而且當它發現定義的 Operation 中涉及到了復雜類型數據, Axis 會自動加上 typeMapping 元素,但是它默認給這個元素上定義的 Deserializer , Serializer 是針對 JavaBean 的,所以如果我們的類是是 EMF ,只要將 typeMapping 的類型改成 EMFSerializerFactory 以及 EMFDeserializerFactory 就可以了。


    5.
    總結


    上面是小弟的一點愚見,請各位看官多提意見


    評論

    # re: 讓Axis支持EMF模型  回復  更多評論   

    2006-09-18 12:21 by 化工
    樓主說的確實對我很有用,多謝了!@_@~~

    # re: 讓Axis支持EMF模型  回復  更多評論   

    2008-02-27 20:03 by zyymmm
    對我很有幫助啊,不過對于我這樣的菜鳥來說,代碼過于省略了,看著費勁

    # re: 讓Axis支持EMF模型  回復  更多評論   

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

    我的郵箱: zyymmm@163.com

    # re: 讓Axis支持EMF模型  回復  更多評論   

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

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

    # re: 讓Axis支持EMF模型  回復  更多評論   

    2008-02-28 11:36 by 趙宇明
    哦,樓主,我發現下載鏈接了,不好意思。
    方便的時候,能否在QQ或MSN上加我?真的非常希望能認識您這樣的高手!非常真誠的,^_^
    主站蜘蛛池模板: 亚洲av日韩av无码黑人| 亚洲国产电影在线观看| 99re免费99re在线视频手机版| 亚洲图片中文字幕| 免费人成视频在线观看不卡| 最新国产乱人伦偷精品免费网站| 亚洲人成777在线播放| 免费A级毛片无码A| 久久w5ww成w人免费| 猫咪免费人成网站在线观看入口| 亚洲av无码专区在线播放| 成年人在线免费观看| 一区二区三区无码视频免费福利| 亚洲码欧美码一区二区三区| 国产AV无码专区亚洲AV毛网站 | 午夜亚洲国产精品福利| 亚洲av无码无在线观看红杏| 日本一道一区二区免费看 | 免费人妻精品一区二区三区| 久久精品国产亚洲77777| 免费人成视频在线观看视频 | 亚洲精品国产日韩无码AV永久免费网 | 精品国产免费一区二区三区香蕉| 亚洲第一第二第三第四第五第六| 久久久久亚洲Av片无码v| 啊v在线免费观看| 在线a级毛片免费视频| 国产成人久久AV免费| 日本黄页网址在线看免费不卡| 亚洲国产中文在线二区三区免| 亚洲色婷婷六月亚洲婷婷6月| 韩国免费三片在线视频| 国产成人精品免费视| 国产一级淫片a免费播放口| 老司机午夜免费视频| 国产 亚洲 中文在线 字幕| 亚洲国产人成在线观看69网站| 亚洲综合色成在线播放| 国产大片51精品免费观看| 我要看WWW免费看插插视频| 国产精品爱啪在线线免费观看|