Terry.Li-彬

          虛其心,可解天下之問(wèn);專其心,可治天下之學(xué);靜其心,可悟天下之理;恒其心,可成天下之業(yè)。

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評(píng)論 :: 0 Trackbacks
          前言
            
            Axis是Apache組織推出的SOAP引擎,Axis項(xiàng)目是Apache組織著名的SOAP項(xiàng)目的后繼項(xiàng)目。Axis為開(kāi)發(fā)者提供了大量的序列化/反序列化器,能夠基本滿足大部分應(yīng)用。但在某些情況下,對(duì)特定的對(duì)象,現(xiàn)有的序列化/反序列化器不能勝任,于是只有開(kāi)發(fā)人員自己實(shí)現(xiàn)專用于此對(duì)象的序列化/反序列化器插入到Axis中來(lái)完成序列化工作。考慮到Web Service是一門新興技術(shù),中文資料大多是泛泛的講解,關(guān)于序列化/反序列化器的開(kāi)發(fā)鮮有較為深入的介紹,本文提供一份較為完整的開(kāi)發(fā)指南,并提供了一個(gè)十分有用的實(shí)現(xiàn),即序列化JDOM模型的Element,使其可以通過(guò)Web 服務(wù)在網(wǎng)絡(luò)上傳輸,我想這一擴(kuò)展是許多采用JDOM作為XML解析工具的開(kāi)發(fā)人員都?jí)裘乱郧蟮墓δ堋Mㄟ^(guò)本文的介紹和實(shí)例,希望能起到拋磚引玉的作用,讀者在閱讀完本文之后可以輕松的實(shí)現(xiàn)針對(duì)于任何非符合BEAN規(guī)范的對(duì)象的序列化/反序列化器。
            
            本文所面對(duì)的讀者需要有一定的使用Axis做Web服務(wù)開(kāi)發(fā)的開(kāi)發(fā)經(jīng)驗(yàn),因此關(guān)于如何Axis的基礎(chǔ)知識(shí)并不在本文的介紹范圍,如果讀者對(duì)此感興趣,可以參考本文最后的參考資料部分,去相應(yīng)的網(wǎng)站進(jìn)行學(xué)習(xí)。
            
            序列化/反序列化器簡(jiǎn)介
            
            序列化/反序列化器在英文中的對(duì)應(yīng)翻譯是Serializer/Deserializer,一個(gè)序列化器的功能是遵循一定的映射規(guī)則和編碼風(fēng)格,將一種類型的JAVA對(duì)象通過(guò)某種特定的機(jī)制,轉(zhuǎn)換成為XML描述的形式;反序列化器的功能是序列化器所做工作的逆操作,兩者相輔相成,成對(duì)出現(xiàn)。Axis中的序列化/反序列化器采用設(shè)計(jì)范式中的工廠模式,每一個(gè)Serializer唯一對(duì)應(yīng)一個(gè)SerializerFactory;每一個(gè)Deserializer唯一對(duì)應(yīng)一個(gè)DeserializerFactory。一種類型的JAVA對(duì)象具體要采用哪個(gè)序列化/反序列化器需要在提供Web服務(wù)的服務(wù)器和調(diào)用Web服務(wù)的客戶端分別配置,關(guān)于這一部分如何配置,我將在本文后面的內(nèi)容中進(jìn)行詳細(xì)介紹。Axis已經(jīng)為開(kāi)發(fā)者提供了豐富的序列化/反序列化器,對(duì)于java的基本數(shù)據(jù)類型,絕大部分常用的容器類(比如數(shù)組類型,Vector類型等)都提供了實(shí)現(xiàn),特別是提供了對(duì)W3C的DOM對(duì)象(比如Document, Element等)和符合Bean規(guī)范的JAVA對(duì)象提供了功能完善的序列化/反序列化器,因此我們?cè)谛枰臅r(shí)候只要在配置文件中配置一下就可以直接使用。如果對(duì)象中包含其它類型的對(duì)象,比如Vector中包含一組Bean對(duì)象,Axis會(huì)自動(dòng)疊代的調(diào)用序列化器,最終拼裝成唯一的XML表述。在還原成JAVA對(duì)象時(shí),也遵循這樣的疊代操作逆向進(jìn)行。關(guān)于Axis到底內(nèi)置了哪些序列化/反序列化器,您可以參照Axis的API文檔中包org.apache.axis.encoding.ser下的類的名稱"望文生義"的了解一下,在以后的開(kāi)發(fā)中做到心中有數(shù)。但對(duì)于一些特殊類型的對(duì)象(其實(shí)我們自己開(kāi)發(fā)的很大一部分類都是這種特殊類型的對(duì)象,很少有絕對(duì)符合Bean規(guī)范的),需要通過(guò)Web服務(wù)進(jìn)行傳遞,我們不得不開(kāi)發(fā)自己的序列化/反序列化器。
            
            開(kāi)發(fā)篇
            
            開(kāi)發(fā)自己的序列化/反序列化器是一個(gè)激動(dòng)人心的工作,但是卻并不復(fù)雜,需要做的事情包括實(shí)現(xiàn)名成為org.apache.axis.encoding的包中的SerializerFactory,Serializer,DeserializerFactory和Deserializer這四個(gè)接口。下面我將結(jié)合一個(gè)實(shí)例來(lái)講解序列化/反序列化器的開(kāi)發(fā)方法,希望讀者能夠一邊參看本文提供的源代碼一邊學(xué)習(xí)。
            
            JDOM作為一款比較"另類"的XML解析工具(因?yàn)樗环蟇3C的DOM模型,自己另立一套)默默地占領(lǐng)著java世界里的xml解析器的半壁江山,由于其簡(jiǎn)潔的設(shè)計(jì)和方便靈活的API調(diào)用,已經(jīng)漸漸成為了許多開(kāi)發(fā)人員在進(jìn)行XML開(kāi)發(fā)的首選。但是Axis是建立在W3C的DOM模型的基礎(chǔ)之上,師出名們正派,自然不屑與JDOM為伍。因此當(dāng)開(kāi)發(fā)人員想將自己已經(jīng)寫好的基于JDOM的應(yīng)用模塊采用Web服務(wù)的方式發(fā)布的時(shí)候,不可避免的會(huì)遇到如何將JDOM模型下的對(duì)象如Document, Element等序列化的問(wèn)題。在軟件工程師不會(huì)自己擴(kuò)展Axis的序列化/反序列化器的時(shí)候,我們只能有兩個(gè)辦法達(dá)到這個(gè)目的,第一個(gè)就是更改以前應(yīng)用模塊內(nèi)的API設(shè)計(jì),使暴露的入口參數(shù)和返回值參數(shù)都是W3C的對(duì)象類型,但這種做法并不現(xiàn)實(shí),因?yàn)檫@一應(yīng)用模塊往往不是獨(dú)立存在,牽一發(fā)將動(dòng)全身,導(dǎo)致舊有系統(tǒng)架構(gòu)的崩塌;另一種做法就是為這個(gè)模塊做一個(gè)代理類,它做的工作就對(duì)外接收或返回DOM模型的對(duì)象,對(duì)內(nèi)轉(zhuǎn)換成JDOM模型的對(duì)象,然后轉(zhuǎn)發(fā)給應(yīng)用模塊,繁瑣且效率低下。當(dāng)我們向Axis注入了針對(duì)于JDOM模型的序列化/反序列化器后,這一工作便可以由Axis代勞了。下面我們將逐個(gè)開(kāi)發(fā)這四個(gè)類:
            
            JDomElementSerializerFactory
            
            JDomElementSerializerFactory是一個(gè)工廠類,需要通過(guò)某種機(jī)制注冊(cè)到Axis引擎(具體方法見(jiàn)下面"服務(wù)器端應(yīng)用篇");Axis通過(guò)調(diào)用它,來(lái)實(shí)例化JDomElementSerializer。Axis 提供了BaseSerializerFactory,這個(gè)類是一個(gè)抽象類,并實(shí)現(xiàn)其中包含了一些可重用的代碼。我們自己開(kāi)發(fā)的工廠類只需簡(jiǎn)單繼承這個(gè)類就可以。構(gòu)造函數(shù)中需要調(diào)用父類的構(gòu)造函數(shù)將序列器類下面是它的源代碼:
            
            package org.apache.axis.encoding.ser;
            
            public class JDomElementSerializerFactory
            extends BaseSerializerFactory {
            
            public JDomElementSerializerFactory()
            }
            
            JDomElementSerializer
            
            JDomElementSerializer實(shí)現(xiàn)org.apache.axis.encoding.Serializer接口,其核心API是serialize(),我們需要在這個(gè)方法的內(nèi)部完成對(duì)JDOM模型的Element的序列化工作,序列化的結(jié)果要保存在入口參數(shù)傳入的序列化上下文對(duì)象(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對(duì)象
            Element root=(Element)value;
            
            //輸出到StringWriter
            XMLOutputter outputter=new XMLOutputter();//創(chuàng)建一個(gè)JDOM的XML輸出器
            StringWriter sw=new StringWriter();
            outputter.output(root,sw);
            
            //用支持W3C的DOM模型的Xerces解析器解析文本流
            DOMParser parser=new DOMParser();//創(chuàng)建一個(gè)DOM的XML解析器
            try {
            parser.parse(new org.xml.sax.InputSource(
            new java.io.StringReader(sw.toString())));
            }catch (Exception ex) {
            throw new java.io.IOException("序列化時(shí)產(chǎn)生錯(cuò)誤");
            }
            
            //獲取符合DOM模型的Element對(duì)象
            org.w3c.dom.Element w3c_root =
            parser.getDocument().getDocumentElement();
            
            //放入序列化上下文對(duì)象中
            context.startElement(name, attributes);
            context.writeDOMElement(w3c_root);
            context.endElement();
            }
            
            JDomElementDeserializerFactory
            
            反序列化器的工廠類同序列化器的工廠類一樣的設(shè)計(jì),在此不在贅述。代碼:
            
            package org.apache.axis.encoding.ser;
            
            public class JDomElementDeserializerFactory
            extends BaseDeserializerFactory {
            
            public JDomElementDeserializerFactory()
            
            }
            
            JDomElementDeserializer
            
            用過(guò)SAX解析XML的讀者,對(duì)反序列化的實(shí)現(xiàn)比較容易理解,反序列化也采用了消息觸發(fā)的機(jī)制,我們只需繼承org.apache.axis.encoding.DeserializerImpl類,并覆蓋其中的onEndElement方法:
            
            /**
            * 在元素結(jié)束觸發(fā)反序列化的方法
            * @param namespace String 命名空間
            * @param localName String 本地名稱
            * @param context DeserializationContext 反序列化上下文
            * @throws SAXException
            */
            public void onEndElement(String namespace, String localName,
            DeserializationContext context) throws SAXException {
            
            try {
            //從反序列化上下文對(duì)象中獲取原始的消息元素
            MessageElement msgElem = context.getCurElement();
            if (msgElem != null) {
            MessageContext messageContext = context.getMessageContext();
            Boolean currentElement = (Boolean) messageContext.getProperty(
            DESERIALIZE_CURRENT_ELEMENT);
            
            //如果當(dāng)前的消息元素本身需要反序列化
            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();
          posted on 2007-11-24 14:42 禮物 閱讀(377) 評(píng)論(0)  編輯  收藏 所屬分類: webservice
          主站蜘蛛池模板: 若羌县| 馆陶县| 屏南县| 赣州市| 手游| 三河市| 额济纳旗| 思南县| 宝应县| 鹤壁市| 锡林浩特市| 文昌市| 石泉县| 石城县| 安庆市| 双江| 互助| 广灵县| 安徽省| 常宁市| 云和县| 宜丰县| 乐都县| 伊宁市| 福贡县| 阿克陶县| 阿尔山市| 准格尔旗| 盖州市| 江城| 左云县| 蓬安县| 鹤岗市| 西青区| 多伦县| 江安县| 额济纳旗| 松滋市| 井陉县| 玉溪市| 资溪县|