一、简介
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串传递数据