一、簡介
XML-RPC的全稱是XML Remote Procedure Call,即XML遠程方法調用。
它是一套允許運行在不同操作系統、不同環境的程序實現基於Internet過程調用的規范和一系列的實現。 這種遠程過程調用使用http作為傳輸協議,XML作為傳送信息的編碼格式。 XML-RPC的定義盡可能的保持了簡單,但同時能夠傳送、處理、返回復雜的數據結構。
XML-RPC的可用版本
XML-RPC client和XML-RPC server都有很多版本的實現。一般而言,一個實現版本都會同時實現client/server。但由於都滿足xml rpc規范,從理論上講,任何一個版本的XML-RPC client實現與任何一個版本的XML-RPC server都能配套使用。
更進一步,由於XML-RPC以XML文本的方式,使用http協議傳輸,所以與編程語言無關。例如:XML-RPC client的已實現版本包括了:perl,php,python,c/c++,java,等等;XML-RPC server的實現語言包括perl,java,等。
同一種編程語言所實現的版本也不止一個。例如java版的實現有:
Marque的XML-RPC現在已經和Redstone XML-RPC Library合並(http://xmlrpc.sourceforge.net/)
Apache的XML-RPC實現,這個項目隸屬於apache web service項目,故URL地址開頭為ws.apache(http://ws.apache.org/)下載鏈接http://archive.apache.org/dist/ws/有些時候直接點進項目去,無法通過鏡像下載,這時候就可以訪問http://archive.apache.org/通過這個鏈接可以下載apache的任何資源。話說apache真是偉大呀!
這個網頁講的真是太好了,雖然是英語:http://www.tutorialspoint.com/xml-rpc/xml_rpc_quick_guide.htm
這個網頁講的有點深:http://www.ibm.com/developerworks/cn/webservices/1211_zhusy_rpc/
二.python實現
python實現參見此博客,此人是一代神牛,更何況是個女的。http://blog.csdn.net/abcjennifer/article/details/38393185
創建服務器,構造方法,注冊方法
from SimpleXMLRPCServer import SimpleXMLRPCServer
def is_even(n):
return n%2 == 0
server = SimpleXMLRPCServer(("localhost", 8000))#確定URL和端口
print "Listening on port 8000..."
server.register_function(is_even, "is_even") #注冊is_even函數
server.serve_forever()#啟動服務器,並使其對這個連接可用
創建客戶端,請求方法
import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
print "3 is even: %s" % str(proxy.is_even(3))#客戶端調用XML-RPC函數
print "100 is even: %s" % str(proxy.is_even(100))
三.xmlrpc++是C++版的xml-rpc接口實現
四.java大法好,一統天下
apache的XML-RPC似乎發生了很大改變,變得極為嚴謹。
下面的代碼分為服務器端和客戶端兩部分,故意用了用一句話編程。讀之給人一種一氣呵成,氣貫長虹之感。功能是:服務器端有兩個函數add和sub,客戶端請求其中之一並傳入兩個int類型的參數,返回int類型的結果並輸出。
服務器端代碼:
class RPCServer {
public static void main(String[] args) throws IOException {
WebServer server = new WebServer(8080);
server.getXmlRpcServer().setHandlerMapping(new XmlRpcHandlerMapping() {
@Override
public XmlRpcHandler getHandler(String handlerName)
throws XmlRpcNoSuchHandlerException, XmlRpcException {
switch (handlerName) {
case "add" :
return new XmlRpcHandler() {
@Override
public Object execute(XmlRpcRequest arg)
throws XmlRpcException {
int x = (int) arg.getParameter(0),
y = (int) arg.getParameter(1);
return x + y;
}
};
case "sub" :
return new XmlRpcHandler() {
@Override
public Object execute(XmlRpcRequest arg)
throws XmlRpcException {
int x = (int) arg.getParameter(0),
y = (int) arg.getParameter(1);
return x - y;
}
};
default :
return null;
}
}
});
server.start();
}
}
下面是客戶端代碼
class RPCClient { public static void main(String[] args) throws XmlRpcException { XmlRpcClient client = new XmlRpcClient(); int ans = (int) client.execute(new XmlRpcRequest() { int x = 3, y = 6; @Override public int getParameterCount() { return 2; } @Override public Object getParameter(int x) { if (x == 0) return this.x; else return this.y; } @Override public String getMethodName() { return "add"; } @Override public XmlRpcRequestConfig getConfig() { XmlRpcClientConfigImpl x = new XmlRpcClientConfigImpl(); try { x.setServerURL(new URL("http://localhost:8080")); } catch (MalformedURLException e) { e.printStackTrace(); } return x; } }); System.out.println(ans); } }
五.關於metaweblog協議
這個協議應用了XML-RPC,是各大博客統一支持的接口,供用戶使用。百度metaweblog會出來一堆的,用這幾個函數接口就足以訪問博客了。下面以博客園的接口為例簡要介紹:
三個大類九大函數七大結構體:
三個大類是誰?blogger(2個函數),metaWeblog(6個函數),wp(1個函數)
九大函數是誰?
•blogger.deletePost 刪除隨筆
•blogger.getUsersBlogs獲取我的博客,我可能有多個博客
•metaWeblog.editPost修改隨筆
•metaWeblog.getCategories獲取隨筆類別
•metaWeblog.getPost獲取隨筆
•metaWeblog.getRecentPosts獲取最近隨筆
•metaWeblog.newMediaObject新建多媒體對象,其實就是上傳文件,在博客園里面只能上傳圖片,返回圖片的url,這樣這文章中就可以使用這個url了。
•metaWeblog.newPost新建隨筆
•wp.newCategory這個函數似乎是博客園獨有的,可以添加分類
這九大函數根據名稱就能看出來分為三大家子,其中wp這一家只有一個”新建類別“函數,blogger這一家有弟兄倆,這兩個函數都需要appKey,這appKey其實不是必要的,博客園中用不到;metaWeblog是最主要的,包括對隨筆的增改查三種操作,其中查又分為兩種操作:根據postid查詢博客;查詢最近博客。metaWeblog還包括一個上傳文件操作。
七個結構體:
BlogInfo描述博客的id,url,博客名等信息;
Post描述隨筆的發布日期,題目,類別,具體內容等信息;
CategoryInfo描述類別信息;
FileData描述如何傳輸文件,包括文件名及文件內容,其中文件內容采用base64編碼,上傳到服務器后返回一個url,FileData有三個成員變量
bits:文件內容,byte[]類型,推薦使用java.nio一句話的事:Files.readAllBytes(Paths.get("shq.jpg")):byte[]
name:文件名,后綴必須是\.jpg|\.gif|\.png|\.jpeg之一,也就是說只允許上傳圖片
type:文件類型(不需要設置,如果設置了,容易出錯,返回500服務器內部錯誤),服務器自己會解析什么類型,無須告知。
URLData只包含一項URL,寫的博客是一個html,里面嵌套着圖片,圖片以結構體的形式FileData用metaWeblog.newMediaObject上傳到服務器,返回一個url,這樣就可以在html中使用這個url了。
Enclosure包括長度,類型,URL三項。
Source包含url及名稱兩項
以上內容在博客園里可以找到:
方式一:管理>設置選項底部
方式二:在我的首頁,ctrl+u查看網頁源代碼,<header>里面有一個RSD(really simple discovery),進入這個鏈接,它是一個XML,里面包含了博客園的weblog入口。
順道說說RSS和RSD。
RSS:really simple syndication簡易信息聚合,為了人們快速獲取有效信息。
RSD:really simple discovery簡易入口,為了人們快速找到網絡服務入口。
這兩者都是特定領域協議。
六.XML-RPC的數據類型
是不是順序有點亂,覺得應該把這一部分放在前面。其實都行,學習就需要回環往復,由深入淺又由淺入深,沒有必要按部就班,只要會了就行。
6種基本數據類型,2種組合數據類型。XML-RPC說:一切皆value。所以一共有八種value。
<value><int>2323</int></value> <value><double>23.23<double></value> <value><boolean>1或者0</boolean></value> <value><string>weidiao</string></value> <value><dateTime>20021125T02:20:04</dateTime></value>格式顯而易見:yyyyMMddThh:mm:ss <value><base64>ASDFASD9823</base64></value>將任意二進制數據轉換成base64編碼方式。 <value><array><data>里面可以放多個value</data></array></value>我認為data這個標簽有點多余 <value><struct>這里可以放多個member,每一個member都是一個name-value-pair</struct></value>
Basic Data Types in XML-RPC
| Type | Value | Examples |
|---|---|---|
| int or i4 | 32-bit integers between - 2,147,483,648 and 2,147,483,647. | <int>27</int> <i4>27</i4> |
| double | 64-bit floating-point numbers | <double>27.31415</double> <double>-1.1465</double> |
| Boolean | true (1) or false (0) | <boolean>1</boolean> <boolean>0</boolean> |
| string | ASCII text, though many implementations support Unicode | <string>Hello</string> <string>bonkers! @</string> |
| dateTime.iso8601 | Dates in ISO8601 format: CCYYMMDDTHH:MM:SS | <dateTime.iso8601> 20021125T02:20:04 </dateTime.iso8601> <dateTime.iso8601> 20020104T17:27:30 </dateTime.iso8601> |
| base64 | Binary information encoded as Base 64, as defined in RFC 2045 | <base64>SGVsbG8sIFdvcmxkIQ==</base64> |
兩種組合數據類型:數組和結構體。數組表示了一種序列化信息,數組可以包含多種數據類型;結構體其實相當於映射,是鍵值對,是屬性集,是關聯數組。
基本數據類型在xml中表示如下:<value><type>xxxx</type></value>。除了string類型可以省略<type>標簽外,其余五種基本數據類型必須明確注明數據類型(這一點就不要記了,統一處理,<value></value>必須注明數據類型)。
<value> <array> <data> <value><string>This </string></value> <value><string>is </string></value> <value><string>an </string></value> <value><string>array.</string></value> </data> </array> </value>
數組中的元素類型可以有多種:
<value>
<array>
<data>
<value><int>7</int></value>
<value><string>dfdfdf</string></value>
<value><int>-91</int></value>
<value><int>42</int></value>
</data>
</array>
</value>
數組也可以嵌套的,很顯然數組相當於value的一種
<value> <array> <data> <value> <array> <data> <value><int>10</int></value> <value><int>20</int></value> <value><int>30</int></value> </data> </array> </value> <value> <array> <data> <value><int>15</int></value> <value><int>25</int></value> <value><int>35</int></value> </data> </array> </value> </data> </array> </value>
結構體的長相是這樣的:
<value>
<struct>
<member>
<name>givenName</name>
<value><string>Joseph</string></value>
</member>
<member>
<name>familyName</name>
<value><string>DiNardo</string></value>
</member>
<member>
<name>age</name>
<value><int>27</int></value>
</member>
</struct>
</value>
七.發出請求
請求的格式是http請求頭部+xml的具體數據內容,通過post方式發送到服務器。
其中xml內容包括兩大部分:方法名及參數,一旦進入<param></param>標簽,就跟上面那些數據類型一樣一樣的了。
<?xml version="1.0"?> <methodCall> <methodName>circleArea</methodName> <params> <param> <value><double>2.41</double></value> </param> </params> </methodCall>
八.回復的格式
包括兩部分:http頭部+xml具體內容,跟發送時沒多大區別。如你所見,既然有http頭部,那就完全可以保存cookie。
HTTP/1.1 200 OK Date: Sat, 06 Oct 2001 23:20:04 GMT Server: Apache.1.3.12 (Unix) Connection: close Content-Type: text/xml Content-Length: 124 <?xml version="1.0"?> <methodResponse> <params> <param> <value><double>18.24668429131</double></value> </param> </params> </methodResponse>
誰又能保證回復是一定正確的呢?服務器把錯誤信息反饋給用戶.
<?xml version="1.0"?> <methodResponse> <fault> <value> <struct> <member> <name>code</name> <value><int>26</int></value> </member> <member> <name>message</name> <value><string>No such method!</string></value> </member> </struct> </value> </fault> </methodResponse>
既然知道了發送和接受的數據格式,那么我們完全可以自己實現這個XML-RPC協議,不就是向服務器post字符串嗎?post的時候有多種方式,可以同步可以異步,可以用原生的URLConnection也可以用封裝過的HTTPClient。
於是問題轉化為對xml串的生成和解析。xml的生成和解析也有很多庫。完全可以自主開發出一套XML-RPC庫。
九.接下來看什么
WSDL網絡服務描述語言:基於XML描述了web服務的功能,消息格式以及協議細節.
SOAP:基於XML,用於程序之間通過http進行交流
十.內省方法
introspect 一個好的事物必然能夠系統地告訴人們它的一切,而不是藏着掖着。任何好的開源組件都必然對應詳盡的文檔。 XML-RPC規定了三個保留方法用來內省服務器。 什么叫內省(xing),就是朝里看,對里面進行探測。 比如,根據數據庫中的表自動生成實體類(PO,persistent object)叫內省; 在fastjson中把javaBean映射成map對象,需要探知Bean中的全部屬性和get,set方法,這也叫內省; 使用XML-RPC時,調用這三個方法,就可以對服務器提供的可用方法有一個整體的認識。 人類都有一種感覺:如果對一樣事物沒有全局的把控,就不踏實。其實能夠在這種不踏實的感覺下勇猛前行者,最終才能夠變得踏實,要有一種反復咀嚼的精神。 system.listMethods 無參函數,返回全部方法 system.methodSignature 傳入函數名稱 system.methodHelp 傳入函數名稱 第一個函數,返回可用方法列表;第二個函數,返回方法簽名;第三個函數返回函數詳情。 至於返回值是什么類型的,可以通過java中的Object#getClass() 反射得到類型名稱。
十一.XML-RPC的替代者
hessian基於二進制傳遞數據,速度快,但跨平台性比不上純字符串格式的快.
JSON-RPC基於json串傳遞數據
