關于 java (apache xmlrpc) ,delphi (delphi xml-rpc),javascript(jsolait)操作xmlrpc的幾點注意事項。
(lizongbo原創,轉載請注明出處。)
A. java操作xmlrpc.
可以使用 apache xmlrpc http://ws.apache.org/xmlrpc/
1. org.apache.xmlrpc.XmlRpc.setDebug(true);可以打開調試模式,可以看到一些詳細的xmlrpc解析處理日志。
2. 不支持值為null,支持的java類型為:Integer,Boolean,String,Double,java.util.Date(支持其子類),byte[],java.util.Vector,java.util.Hashtable
(http://ws.apache.org/xmlrpc/types.html? apache xmlrpc 對java類型作了擴展,但是如果要考慮其它編程語言的調用,不建議使用擴展的類型)
B. delphi操作xmlrpc的庫是delphixml-rpc:http://sourceforge.net/projects/delphixml-rpc/
(網上有人提到過codepunk,但是現在已經無法下載.http://www.codepunk.com/xmlrpc1_7_6.zip ,參考:http://www.delphibbs.com/keylife/iblog_comment.asp?xid=870)
于是選擇了delphixml-rpc,實際使用中遇到以下一些問題,
1.漢字處理的問題。 delphi作客戶端,? java作服務端,產生
Hello, 你好 , test  汉字"不能夠轉換成"Hello, 你好 , test 漢字"
的問題, 解決方法如下:
?
xmlrpcparser
1554行,
CHR改成widechar
如下:
????????? THEN CurContent := CurContent + widechar (StrToIntDef ('$'+Copy (Name, 3, MaxInt), 32))
????????? ELSE CurContent := CurContent + widechar (StrToIntDef (Copy (Name, 2, MaxInt), 32));
對于sf上最新的xmlrpc包,則需要修改LibxmlPraser.pas對應地方的代碼
2.空字符串(非null)的解析問題。
java 的代碼: Hashtable struct = new Hashtable();
??????? struct.put("type", new Integer(0));
??????? struct.put ("id", "0"); //如果這樣寫 struct.put("id", ""); ,就會導致結構體錯亂 ,取不到第一個 struct
解決辦法,通過一個約定的字符串“nil”來表示空字符串。
3. 使用ssl遇到的問題:
tomcat的 ssl配置為:
??? <Connector port="8083"
?????????????? maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
?????????????? enableLookups="false" disableUploadTimeout="true"
?????????????? acceptCount="100" scheme="https" secure="true"
?????????????? clientAuth="false" sslProtocol="TLS"
?????????? keystoreFile="conf/ca/.keystore"
?????????? keystorePass="password">
???? </Connector>
?
而delphi的xmlrpc調用會出問題,因此需要修改源代碼:
在XmlRpcClient.pas的第321行之后加上下面兩行代碼:
?
??????? IdSSLIOHandlerSocket.SSLOptions.Mode := sslmUnassigned;
??????? IdSSLIOHandlerSocket.SSLOptions.Method := sslvTLSv1;
?
?(如果tomcat使用了apr,則ssl配置是不一樣的,這種情況下的delphi調用,我們沒測試過)
4.亂碼導致結構體解析失敗
?
如果結構體的string里有不可識別的字符,會導致結構體解析失敗,
因此,在傳輸的內容為不可預見的情況下(比如用戶發送的千奇百怪的短消息),
建議用byte傳送(實際工作中遇到這樣的情況并總結出來的。)
服務端 :struct.put ("msg", "測試短消息"); ---> struct.put ("msgbyte", "測試短消息".getBytes());
客戶端delphi代碼改用asBase64str方法來還原為string.
(以上均是實際工作中遇到的問題。 )
C .jsolait的xmlrpc庫是javascript的操作xmlrpc的,非常簡單.
多個參數的調用可以放在一個數組,也可以分別傳入,同jdk1.5的可變參數(Variable Arguments)。
如果只傳一個參數,而這個參數是個數組,需要這樣寫:
var xmlrpc=null;
?try{
??? var xmlrpc = importModule("xmlrpc");
?}catch(e){
??? reportException(e);
??? throw "importing of xmlrpc module failed.";
?}
?var addr = "http://lizongbo:808/lizongbo/xmlrpc";
?var methods = ["lizongbo.testOneArray"];
?var rslt;
?var params = new Array();
?params[0] = "0311112";
?params[1] = "awsasaas";
?params[2] = "awsasaas";
?try{
?????? var service = new xmlrpc.ServiceProxy(addr, methods);
?????? rslt = service.lzbrpc.testOneArray([params]);//用中括號括起來,否則會被解析為三個傳入參數的調用
?????? ///service.lzbrpc.testOneArray(params) 等同于service.lzbrpc.testOneArray(params[0],params[1],params[2]);
?????? 返回結果里如果只有一個值,可以直接在用rslt,如果有多個值,
?????? 比如下面這個結構體, 則可以用rslt.flag,rslt.info,rslt.struct.version來分別得到對應的值。
?????? (符合dom)
// var str="" + rslt.flag+' xx '+rslt.info+' yy '+rslt.struct.version ;
// 或者var str="" + rslt['flag']+' xx '+rslt['info']+' yy '+rslt['struct']['version'];
//得到的結果是"1 xx 成功 yy 123.beta "
參考 : http://www.tkk7.com/mstar/archive/2005/06/07/5657.aspx
?
D . 調試xmlrpc,有一個非常優秀的工具:
http://torrez.net/projects/konstructor/Konstructor.exe
來自:
http://torrez.net/archives/xmlrpc_request_builder.php
缺點,只能夠連接類似 http://lizongbo.com/xmlrpc的Endpoint
不支持https,也不支持除80外的其它端口
(lizongbo原創,轉載請注明出處。)