zoukankan      html  css  js  c++  java
  • 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

    TypeValueExamples
    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串传递数据

  • 相关阅读:
    将数据导入第三方系统
    希望可以看到自己的积分
    WF疑惑
    GUID
    wf HandlExternalEvent传递参数到自定义属性中
    今天做了一天的网站,烦恼
    WF 参数传递,今天终于把WORKFLOW的参数回传回来了
    今天开始在这里写博了
    寻求帮助,怪问题
    WF终于有了一点入门的感觉
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/5293871.html
Copyright © 2011-2022 走看看