面對本文的讀者需要有壹些使用Axis開發Web服務的經驗,所以關於如何開發Axis的基礎知識超出了本文的範圍。如果讀者對此感興趣,可以參考本文末尾的參考資料部分,並前往相應的網站進行學習。
串行器/解串器簡介
serializer/deserializer在英語中對應的翻譯是Serializer/Deserializer。序列化器的作用是遵循壹定的映射規則和編碼風格,通過壹定的機制將壹類JAVA對象轉換成XML描述的形式。反序列化器的作用是序列化器所做工作的逆向操作,兩者相輔相成,成對出現。Axis中的序列化器/反序列化器采用了設計範式中的工廠模式,每個序列化器唯壹對應壹個SerializerFactory;每個反序列化器都唯壹地對應於壹個反序列化工廠。需要在提供Web服務的服務器和調用Web服務的客戶機中分別配置哪種序列化程序/反序列化程序應該用於壹種類型的JAVA對象。我將在本文後面詳細介紹如何配置這壹部分。Axis為開發人員提供了豐富的序列化器/反序列化器。對於java的基本數據類型,大部分常用的容器類(如數組類型、向量類型)都已經實現,特別是W3C DOM對象(如Document、Element)和符合Bean規範的JAVA對象,只要在需要的時候在配置文件中配置就可以直接使用。如果對象包含其他類型的對象,比如Vector中的壹組Bean對象,Axis會自動叠代調用序列化器,最後組裝成壹個唯壹的XML表達式。當恢復到JAVA對象時,我們也反過來遵循這個叠代操作。至於axis內置了哪些序列化器/反序列化器,可以參考Axis的API文檔中org.apache.axis.encoding.ser包下的類的名稱,以便在以後的開發中心中有數。但是對於壹些特殊類型的對象(其實我們自己的類很大壹部分就是這種特殊類型的對象,很少有絕對符合Bean規範的),我們就要自己開發序列化器/反序列化器了。
發展文章
開發自己的序列化器/反序列化器是壹項令人興奮的工作,但並不復雜。需要做的包括在名為org.apache.axis.encoding的包中實現SerializerFactory、Serializer、DeserializerFactory、Deserializer四個接口接下來我用壹個例子來說明serializer/deserializer的開發方法。希望讀者可以壹邊參考本文提供的源代碼,壹邊學習。
JDOM作為壹個“另類”的xml解析工具(因為不符合W3C DOM模型,所以另立壹套),默默占據了java世界XML解析器的半壁江山。由於其簡潔的設計和方便靈活的API調用,JDOM逐漸成為很多開發者在XML開發中的首選。而Axis基於W3C的DOM模型,名師正派,自然不屑與JDOM交往。因此,當開發人員希望通過Web服務的方式發布他們已經編寫好的基於JDOM的應用模塊時,他們不可避免地會遇到如何序列化JDOM模型下的文檔、元素等對象的問題。當軟件工程師不自己擴展Axis的序列化器/反序列化器時,只有兩種方法可以達到這個目的。首先是改變之前應用模塊中的API設計,讓暴露的入口參數和返回參數都是W3C對象類型,但這並不現實,因為這個應用模塊往往並不是獨立存在的,這會導致舊的系統架構崩潰。還有壹種方式是給這個模塊做壹個代理類,它的工作就是對外接收或者返回DOM模型的對象,對內轉換成JDOM模型的對象,然後轉發給應用模塊,這種方式比較繁瑣,效率也不高。當我們將JDOM模型的序列化器/反序列化器註入Axis時,這項工作可以由Axis來完成。我們將逐壹開發這四個類:
JDomElementSerializerFactory
JDomElementSerializerFactory是壹個工廠類,需要通過某種機制註冊到Axis引擎(具體方法見下面的“服務器端應用”);Axis通過調用JDomElementSerializer來實例化它。Axis提供了BaseSerializerFactory,這是壹個抽象類,它的實現包含壹些可重用的代碼。我們自己開發的工廠類就是簡單的繼承了這個類。需要調用構造函數中父類的構造函數將是sequencer類。下面是它的源代碼:
包org . Apache . axis . encoding . ser;
公共類JDomElementSerializerFactory
擴展BaseSerializerFactory {
公共JDomElementSerializerFactory(){
super(jdomelementserializer . class);
}
}
JDomElementSerializer
JDomElementSerializer實現org . Apache . axis . encoding . serializer接口,其核心API是serialize()。我們需要序列化這個方法內部的JDOM模型的元素,序列化的結果要保存在entry參數傳入的SerializationContext中:
public void serialize(QName名稱、屬性屬性、對象值,
SerializationContext上下文)引發java.io.IOException {
如果(!(元素的值實例))
拋出新的IOException(
messages . getmessage(" cant Serialize Object "));
//獲取符合JDOM的元素對象。
元素根=(元素)值;
//輸出到StringWriter
XMLOutputter outputter = new XMLOutputter();//為JDOM創建XML導出程序。
string writer SW = new string writer();
outputter.output(root,SW);
//用支持W3C DOM模型的Xerces解析器解析文本流。
DOM parser parser = new DOM parser();//為DOM創建XML解析器。
嘗試{
parser . parse(new org . XML . sax . input source(
new Java . io . string reader(SW . tostring())));
}catch (Exception ex) {
拋出new java.io.IOException("序列化時出錯");
}
//獲取符合DOM模型的元素對象。
org.w3c.dom.Element w3c_root =
parser.getDocument()。getDocumentElement();
//到序列化上下文對象中
context.startElement(名稱,屬性);
context . writedomelement(W3C _ root);
context . end element();
}
JDomElementDeserializerFactory
反序列化器的工廠類和序列化器的工廠類設計壹樣,這裏就不贅述了。代碼:
包org . Apache . axis . encoding . ser;
公共類JDomElementDeserializerFactory
擴展BaseDeserializerFactory {
公共jdomelementdeseriazerfactory(){
super(jdomelementdeserializer . class);
}
}
JDomElementDeserializer
用過SAX解析XML的讀者很容易理解反序列化的實現,反序列化也采用消息觸發的機制。我們只需要繼承org . Apache . axis . encoding . deserialize impl類,並在其中覆蓋onEndElement方法:
/**
*在元素末尾觸發反序列化的方法
* @param名稱空間字符串名稱空間
* @param localName字符串本地名稱
* @ paramcontext反序列化上下文
* @拋出SAXException
*/
public void onEndElement(字符串命名空間,字符串localName,
反序列化上下文上下文)引發SAXException {
嘗試{
//從反序列化上下文對象中獲取原始消息元素。
message element msg elem = context . getcurelement();
if (msgElem!= null) {
message context message context = context . getmessagecontext();
Boolean current element =(Boolean)message context . getproperty(
反序列化_當前_元素);
//如果當前消息元素本身需要反序列化
if (currentElement!= null & amp& ampcurrent element . boolean value()){
org . W3C . DOM . element element = msg elem . getas DOM();
org . JDOM . input . DOM builder db = new org . JDOM . input . DOM builder();
value = db . build(element);
message context . set property(DESERIALIZE _ CURRENT _ ELEMENT,
布爾型。假);
返回;
}
//反序列化消息元素中的消息體
Java . util . ArrayList children = msg elem . get children();
如果(孩子!= null) {
//獲取消息正文
msg elem =(message element)children . get(0);
if (msgElem!= null) {
org . W3C . DOM . element ret = msg elem . getas DOM();
org . JDOM . input . DOM builder db = new org . JDOM . input . DOM builder();
//用DOMBuilder將DOM模型的元素轉換成JDOM模型的元素。
value = db . build(ret);
}
}
}
}
catch(例外){
//錯誤,然後記錄並拋出SAXException。
log . error(messages . getmessage(" exception 00 "),ex);
拋出新的sax exception(ex);
}
}
編碼完這四個類,序列化器/反序列化器的開發就基本完成了,下面會詳細講解使用和部署方法。
服務器應用文章
為了簡單起見,我們通過Web服務發布了壹個非常簡單的類。類中只有壹個名為hello的函數,函數的返回值是JDOM模型的元素。代碼如下:
包裝測試;
導入org . JDOM . *;
導入Java . RMI . remote exception;
公共類Sample1實現java.rmi.Remote{
公共樣本1() {
}
公共元素hello(字符串名稱){
元素根=新元素(“根”);
Element hello =新元素(“hello”);
hello.setText("hello,"+name+"!");
root . add content(hello);
返回根目錄;
}
}
這裏不介紹如何將類發布為Web服務。相信讀者自己也能做到。我們只關註如何向我們的Web服務添加序列化程序/反序列化程序。打開web服務的配置文件server-config.xml,編輯Sample1服務的配置部分:
& ltservice name = " sample 1 " type = " " regenerate element = " true "
provider = " Java:RPC " style = " RPC " use = " encoded " & gt;
& ltparameter name = " scope " value = " Request " regenerate element = " false "/& gt;
& lt參數name="className" value="test。sample 1 " regenerate element = " false "/& gt;
& ltparameter name = " allowed methods " value = " * " regenerate element = " false "/& gt;
& lt類型映射
encoding style = "/develop/Read _ article . ASP?Id=13806