<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 閱讀(2012) 評論(5)  編輯  收藏 所屬分類: SCA 、EMF

    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上加我?真的非常希望能認識您這樣的高手!非常真誠的,^_^
    主站蜘蛛池模板: 在线免费中文字幕| 免费一级毛片一级毛片aa| 亚洲人成电影院在线观看| 国产精品色午夜视频免费看| 人成午夜免费大片在线观看| 久久久国产精品亚洲一区| 永久免费bbbbbb视频| 久久免费国产视频| 亚洲av中文无码字幕色不卡| 亚洲熟女少妇一区二区| 好吊妞在线成人免费| 国产真人无码作爱视频免费| 亚洲性色精品一区二区在线| 亚洲真人无码永久在线| 成人啪精品视频免费网站| 成人精品视频99在线观看免费| 亚洲天堂福利视频| 4338×亚洲全国最大色成网站| 91九色精品国产免费| 国产免费久久精品丫丫| 亚洲首页国产精品丝袜| 亚洲s色大片在线观看| 国产又大又长又粗又硬的免费视频 | 久久久久久久久久国产精品免费| 亚洲Av永久无码精品一区二区| 久久国产精品亚洲综合| 亚洲av日韩片在线观看| 日本片免费观看一区二区| 国产免费久久精品丫丫| 久久亚洲AV成人无码国产电影| 亚洲欧洲视频在线观看| 亚洲男同帅GAY片在线观看| 男人的天堂亚洲一区二区三区| 免费国产成人18在线观看| 免费国产在线精品一区| 一本天堂ⅴ无码亚洲道久久| 亚洲专区在线视频| 亚洲色欲色欲www在线丝| www.亚洲精品| 国产日产成人免费视频在线观看| 国产免费久久精品99re丫y|