XML-RPC遠程方法調用


 一、簡介

XML-RPC的全稱是XML Remote Procedure Call,即XML遠程方法調用。

它是一套允許運行在不同操作系統、不同環境的程序實現基於Internet過程調用的規范和一系列的實現。 這種遠程過程調用使用http作為傳輸協議,XML作為傳送信息的編碼格式。 XML-RPC的定義盡可能的保持了簡單,但同時能夠傳送、處理、返回復雜的數據結構。

XML-RPC是使用HTTP協議做為傳輸協議的RPC(遠程方法調用)機制,使用XML文本的方式傳輸命令和數據。
一個RPC系統,必然包括2個部分:
  1.RPC Client,用來向RPC Server調用方法,並接收方法的返回數據;
  2.RPC Server,用於響應RPC Client的請求,執行方法,並回送方法執行結果。
  RPC是Remote Procedure Call的縮寫,翻譯成中文就是遠程方法調用,是一種在本地的機器上調用遠端機器上的一個過程(方法)的技術,這個過程也被大家稱為“分布式計算”,是為了提高各個分立機器的“互操作性”而發明出來的技術。

 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串傳遞數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM