Xml RPC是什么

xml rpc是什么

        本文转自http://blog.csdn.net/luckyspring/archive/2007/05/23/1623374.aspx

 

1.xml rpc是什么

1.1. xml rpc简介

        xml rpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据。
        一个rpc系统,必然包括2个部分:1.rpc client,用来向rpc server调用方法,并接收方法的返回数据;2.rpc server,用于响应rpc client的请求,执行方法,并回送方法执行结果。

1.2. xml rpc的可用版本

        xml rpc client和xml rpc server都有很多版本的实现。一般而言,一个实现版本都会同时实现client/server。但由于都满足xml rpc规范,从理论上讲,任何一个版本的rpc client实现与任何一个版本的rpc server都能配套使用。
        更进一步,由于xml rpc以xml文本的方式,使用http协议传输,所以与编程语言无关。例如:rpc client的已实现版本包括了:perl,php,python,c/c++,java,等等;rpc server的实现语言包括perl,java,等。
        同一种编程语言所实现的版本也不止一个。例如java版的实现有:Marque的xmlrpc实现( http://xmlrpc.sourceforge.net/),apache的xmlrpc 实现( http://ws.apache.org/xmlrpc/)

1.3.xmlrpc的工作原理

        完整的需要参考xmlrpc规范( http://www.xmlrpc.com/spec)
        简单描述:
        rpcclient的工作原理:rpcclient根据URL找到rpcserver -> 构造命令包,调用rpcserver上的某个服务的某个方法 -> 接收到rpcserver的返回,解析响应包,拿出调用的返回结果。
        rpcserver的工作原理:启动一个webserver(在使用内置的webserver的情况下) -> 注册每个能提供的服务,每个服务对应一个Handler类 ->进入服务监听状态。

1.4. xmlrpc规范

        区区6页,讲的非常清楚,建议细看。 http://www.xmlrpc.com/spec

2.在java中使用xml rpc的几个例子

2.0.环境准备:下载如下包并设置到CLASSPATH中

        apache xmlrpc软件包( http://ws.apache.org/xmlrpc/)
        commons-httpclient-3.0-rc4.jar
        commons-codec-1.3.jar

2.1.使用apache的java xmlrpc实现版本,实现简单的加/减服务。参考附录中test.XmlRPCClient类与test.JavaServer类

2.2.使用apache的java xmlrpc实现版本,测试java的数据类型与xmlrpc数据类型的相互对应关系。参考附录中test2.XmlRPCClient类与test2.JavaServer类。

        在这里简单描述一下:
        >xmlrpc中的Array类型,对应到java中的Vector类型
        例如:在RPC Server中的某个服务方法的返回值的声明类型是String[],但在Client中接收到的将是Vector对象;
        反之,如果Client传送过去的调用参数为String[],但在RPC Server中所接收到的将是Vector对象
        当然,如果我们不使用String[],直接声明为Vector,也是可以的。
        >xmlrpc中的struct类型,对应到java中的Hashtable类型
        >其它的类型,如:String,int,double,boolean,Date等,都比较好对应。需要注意的是:在rpc Client中,如果使用到int/double/boolean这些基本类型时,需要将他们封装成一个相应的Object,例如:Integer/Double/Boolean。

2.3.使用apache的java xmlrpc实现版本,实现自定义类型的数据的传输

        这个sample中,假设所传输的object都实现了XmlRPCSerializable接口。这个例子的目的是:模拟unionmon中的command对象。当假设所传输的数据是一个Object[]时,可以用这种方式传输。结合unionmon中的代码生成机制,每个vo的序列化/反序列化方法可以在代码生成过程中完成。同样地,vox的序列化/反序列化方法需要手写。
        参考代码:附录中的test3.XmlRPCSerializable , test3.AccountVO , test3.XmlRPCClient , test3.JavaServer

2.4.不启动内置的WebServer,让tomcat支持rpc server。

        做法:1.实现一个Servlet,并配置到tomcat中;2.让rpc client直接找这个servlet,获得服务。
        注意rpc client使用的是http post方法,所以该servlet中只需要实现doPost方法。

        过程:在tomcat中的web.xml增加如下配置:

<servlet>
     <servlet-name>SampleServiceServlet</servlet-name>
     <servlet-class>test4.ServletXmlRPCServer</servlet-class>
</servlet>
<servlet-mapping>
     <servlet-name>SampleServiceServlet</servlet-name>
     <url-pattern>/SampleServiceServlet</url-pattern>
</servlet-mapping>

        参考类:附件中的test4.SampleService,test4.ServletXmlRPCServer,test4.XmlRPCClient

3.todolist

3.1.能否通过introspect方式,使得自定义类型的vo的序列化/反序列化工作自动完成.castor可以完成对象的xml binding,似乎可参考

3.2.soap协议比xmlrpc复杂并强大。soap不熟悉。另,soap一定与web service在一起用?能否不用web service,但使用soap做rmi的协议。


4.附录

4.1.附录1 xmlrpc所支持的数据类型(略)
4.2.附录2 xmlrpc数据类型与java语言的数据类型的映射(略)
4.3.参考资料

http://xmlrpc.sourceforge.net/   --Marque的xmlrpc实现
http://ws.apache.org/xmlrpc/ apache上xmlrpc server的实现
http://xmlrpc-c.sourceforge.net/xmlrpc-howto/xmlrpc-howto.html xmlrpc howto
http://www.sentom.net/list.asp?id=80 xml-rpc之实例
http://www.xmlrpc.com/spec xmlrpc规范


4.4.相关代码

//*********************************  begin test.XmlRPCClient  ************************************//
package test;
import java.util.*;
import org.apache.xmlrpc.*;
public class XmlRPCClient {
  // The location of our server.
  private final static String server_url =
      "http://localhost:9001";
  public static void main(String[] args) throws Exception{
      XmlRpc.debug = true;
      // Create an object to represent our server.
      XmlRpcClient server = new XmlRpcClient(server_url);
      // Build our parameter list.
      Vector params = new Vector();
      params.addElement(new Integer(5));
      params.addElement(new Integer(3));
      // Call the server, and get our result.
      Hashtable result = (Hashtable) server.execute("mysample.sumAndDifference",
          params);
      int sum = ( (Integer) result.get("sum")).intValue();
      int difference = ( (Integer) result.get("difference")).intValue();
      System.out.println("Sum: " + Integer.toString(sum) +
                         ", Difference: " +
                         Integer.toString(difference));
  }
}
//*********************************   end test.XmlRPCClient   ************************************//

//**********************************  begin test.JavaServer   ************************************//

package test;
import java.util.*;
import org.apache.xmlrpc.WebServer;
public class JavaServer {
  public JavaServer() {
  }
  public Hashtable sumAndDifference(int x, int y) {
    Hashtable result = new Hashtable();
    result.put("sum", new Integer(x + y));
    result.put("difference", new Integer(x - y));
    return result;
  }
  public static void main(String[] args) {
    try {
      // Invoke me as <http://localhost:9001/RPC2>.
      WebServer webserver = new WebServer(9001);
      webserver.addHandler("mysample", new JavaServer());
      webserver.start();
    }
    catch (Exception exception) {
      System.err.println("JavaServer: " + exception.toString());
    }
  }
}
//**********************************  end test.JavaServer  ************************************//


//**********************************  begin test2.XmlRPCClient  ************************************//

package test2;
import java.util.*;
import org.apache.xmlrpc.*;
public class XmlRPCClient {
  // The location of our server.
  private final static String server_url =
      "http://localhost:9001";
  public static void main(String[] args) {
    try {
      XmlRpc.debug = true;
      XmlRpcClient server = new XmlRpcClient(server_url);
      // Build our parameter list.
      Vector params = new Vector();
      Vector arg0 = new Vector();
      arg0.add("army");
      arg0.add("robin");
      params.addElement(arg0);
      Hashtable arg1 = new Hashtable();
      arg1.put("a","a");
      arg1.put("b","b");
      params.addElement(arg1);
      Integer arg2 = new Integer(3);
      params.addElement(arg2);
      Double arg3 = new Double(11.33);
      params.addElement(arg3);
      Boolean arg4 = new Boolean(false);
      params.addElement(arg4);
      Date arg5 = Calendar.getInstance().getTime();
      params.addElement(arg5);
      // Call the server, and get our result.
      Object ret = server.execute("sample.getAllUser",params);
      Vector result = (Vector)ret;
      if(result!=null){
        System.out.println("result:" + result.size() + "records");
        for(int i=0;i<result.size();i++){
          System.out.println("result " + i + "is:" + result.get(i));
        }
      }
    }
    catch (XmlRpcException exception) {
      System.err.println("XmlRPCClient: XML-RPC Fault #" +
                         Integer.toString(exception.code) + ": " +
                         exception.toString());
    }
    catch (Exception exception) {
      exception.printStackTrace(System.err);
    }
  }
}
//*********************** end test2.XmlRPCClient *********************************//

//*********************** begin test2.JavaServer*********************************//

package test2;
import java.util.*;
import org.apache.xmlrpc.WebServer;
public class JavaServer {
        public JavaServer () {
            // Our handler is a regular Java object. It can have a
            // constructor and member variables in the ordinary fashion.
            // Public methods will be exposed to XML-RPC clients.
        }
        public Vector getAllUser (Vector arg0,Hashtable arg1,int arg2,double arg3,boolean arg4,Date arg5) {
          if(arg0!=null){
            System.out.println(arg0.size());
          }
          if(arg1!=null){
            System.out.println(arg1.size());
          }
          System.out.println(arg2);
          System.out.println(arg3);
          System.out.println(arg4);
          System.out.println(arg5);
            Vector result = new Vector();
            result.add("bruce");
            result.add("测试中文");
            result.add("orbison");
            return result;
        }
        public static void main (String [] args) {
            try {
                // Invoke me as <http://localhost:9001/RPC2>.
                WebServer webserver = new WebServer(9001);
                webserver.addHandler("sample", new JavaServer());
                webserver.start();
            } catch (Exception exception) {
                System.err.println("JavaServer: " + exception.toString());
            }
        }
    }
//*********************** end test2.JavaServer *********************************//

//********************* begin test3.XmlRPCSerializable ****************************//
package test3;
import java.util.Vector;
public interface XmlRPCSerializable {
  /*将本对象序列化为Vector对象*/
  public Vector serialize();
  /*从v中反序列化本对象*/
  public void deSerialize(Vector v);
}
//******************** end test3.XmlRPCSerializable **********************//

//******************** begin test3.AccountVO  *********************//
package test3;
import java.util.*;
public class AccountVO implements XmlRPCSerializable{
  private String acctId;
  private double balance;
  public AccountVO() {
  }
  public String toString(){
    return "acctId:" + acctId + ",balance:" + balance;
  }
  public Vector serialize(){
    Vector v = new Vector();
    v.add(acctId);
    v.add(new Double(balance));
    return v;
  }
  public void deSerialize(Vector v){
    acctId = (String)v.get(0);
    balance = ((Double)v.get(1)).doubleValue();
  }
  public String getAcctId() {
    return acctId;
  }
  public void setAcctId(String acctId) {
    this.acctId = acctId;
  }
  public double getBalance() {
    return balance;
  }
  public void setBalance(double balance) {
    this.balance = balance;
  }
}
//************************ end test3.AccountVO *************************//

//************************ begin test3.XmlRPCClient*************************//
package test3;
import java.util.*;
import org.apache.xmlrpc.*;
public class XmlRPCClient {
  // The location of our server.
  private final static String server_url =
      "http://localhost:9001";
  public static void main(String[] args) {
    try {
      XmlRpc.debug = false;
      // Create an object to represent our server.
      XmlRpcClient server = new XmlRpcClient(server_url);
      // Build our parameter list.
      Vector params = new Vector();
      // Call the server, and get our result.
      Vector result = (Vector) server.execute("mysample.getAllAccountVO",
                                              params);
      if (result != null) {
        for (int i = 0; i < result.size(); i++) {
          Vector v = (Vector) result.get(i);
          AccountVO vo = new AccountVO();
          vo.deSerialize(v);
          System.out.println(vo);
        }
      }
    }
    catch (XmlRpcException exception) {
      System.err.println("XmlRPCClient: XML-RPC Fault #" +
                         Integer.toString(exception.code) + ": " +
                         exception.toString());
    }
    catch (Exception exception) {
      exception.printStackTrace();
    }
  }
}
//************************ end test3.XmlRPCClient*************************//

//************************ begin test3.JavaServer*************************//
package test3;
import java.util.*;
import org.apache.xmlrpc.WebServer;
public class JavaServer {
        public JavaServer () {
        }
        public Vector getAllAccountVO () {
            Vector result = new Vector();
            AccountVO vo = new AccountVO();
            vo.setAcctId("robin");
            vo.setBalance(300000.00);
            result.add(vo.serialize());
            vo = new AccountVO();
            vo.setAcctId("amy");
            vo.setBalance(100000.10);
            result.add(vo.serialize());
            return result;
        }
        public static void main (String [] args) {
            try {
                // Invoke me as <http://localhost:9001/RPC2>.
                WebServer webserver = new WebServer(9001);
                webserver.setParanoid (true);
                // deny all clients
                webserver.acceptClient ("192.168.0.*"); // allow local access
                webserver.denyClient ("192.168.0.3"); // except for this one
                webserver.setParanoid (false); // disable client filter
                webserver.addHandler("sample", new JavaServer());
                webserver.addHandler("mysample",new JavaServer());
                webserver.start();
            } catch (Exception exception) {
                System.err.println("JavaServer: " + exception.toString());
            }
        }
    }
end test3.JavaServer//
//************************ end test3.JavaServer*************************//

//************************ begin test4.SampleService*************************//
package test4;
import java.util.*;
public class SampleService {
  public SampleService() {
  }
  public Date currentTime(){
    return Calendar.getInstance().getTime();
  }
}
end test4.SampleService//
begin test4.ServletXmlRPCServer//
package test4;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.apache.xmlrpc.*;
public class ServletXmlRPCServer
    extends HttpServlet {
  public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
    XmlRpcServer xmlrpc = new XmlRpcServer();
    xmlrpc.addHandler("sampleService", new SampleService());
    byte[] result = xmlrpc.execute(request.getInputStream());
    response.setContentType("text/xml");
    response.setContentLength(result.length);
    OutputStream out = response.getOutputStream();
    out.write(result);
    out.flush();
  }
}
end test4.ServletXmlRPCServer//
//*********************** end test4.ServletXmlRPCServer **************************//

//*********************** begin test4.XmlRPCClient**************************//
package test4;

import java.util.*;
    import org.apache.xmlrpc.*;
    public class XmlRPCClient {
        // The location of our server.
        private final static String server_url =
            "http://localhost:8080/axis/SampleServiceServlet";
        public static void main (String [] args) {
            try {
              XmlRpc.debug = false;
                // Create an object to represent our server.
                XmlRpcClient server = new XmlRpcClient(server_url);
                // Build our parameter list.
                Vector params = new Vector();
                // Call the server, and get our result.
                Date result = (Date) server.execute("sampleService.currentTime", params);
                System.out.println(result.getTime());
            } catch (XmlRpcException exception) {
                System.err.println("XmlRPCClient: XML-RPC Fault #" +
                                   Integer.toString(exception.code) + ": " +
                                   exception.toString());
            } catch (Exception exception) {
                System.err.println("XmlRPCClient: " + exception.toString());
            }
        }
    }
//*********************** end test4.XmlRPCClient**************************//



=======================================================================================

使用XML RPC进行远程调用 

        本文转自http://www.cnblogs.com/chenxizhang/archive/2008/08/23/1274499.html

 

        因为最近研究博客系统,对XML RPC的机制有了更深入的一些了解。下面总结一下

        1. 什么是XML -RPC?为什么需要它?

        有关详细的介绍,你可以参考下面的说明。简单来说,XML-RPC是一个简单的协议和标准,它通过标准的HTTP请求和响应来实现,数据是以xml格式传递的。它的优点是跨平台。如果仅仅在.NET平台,那么它也许并不是一个最好的选择,而另外一种技术SOAP Web Service可能更加好一些

        http://www.xml-rpc.net/faq/xmlrpcnetfaq.html

1.1 What is XML-RPC?

        To quote the XML-RPC.com site:

        "It's a spec and a set of implementations that allow software running on disparate operating systems, running in different environments to make procedure calls over the Internet. It's remote procedure calling using HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned.";

1.2 What is XML-RPC.NET?

        XML-RPC.NET is a .NET class library for implementing XML-RPC clients and servers.

1.3 Why use XML-RPC instead of SOAP?

        If your clients and servers are all running in the .NET environment there is no point in using XML-RPC: .NET provides excellent support for SOAP and XML-RPC doesn't have any features not provided by SOAP (other than simplicity).

If you use .NET clients and want to connect to XML-RPC servers running under any OS then XML-RPC.NET is a good choice.

If you want to implement a server in the .NET environment which is to be connected to by clients running in other environments, say Unix or Java, then XML-RPC may be an appropriate choice. SOAP is supported in many different environments but is considerably more complicated than XML-RPC and presents more opportunity for interop problems

        我们在这里要感谢Cook这个人,是他将XML-RPC进一步标准化,目前我们大部分人使用的XML-RPC组件,都叫做CookComputing.XmlRpc

        这里还有一个介绍(中文的)http://www.mengyan.org/blog/archives/2005/07/12/30.html

2. 博客系统中的XML RPC

        下面有一篇文章很好地介绍了该过程 http://nayyeri.net/blog/implement-metaweblog-api-in-asp-net/

        典型的博客客户端都实现了该协议。例如Windows Live Writer等等。下面三个图片就展示了如何在WLW中添加一个博客账户的界面。甚至连Word 2007也实现了该功能。

image image image

3. 实现自定义的XML RPC

        抛开博客系统,如果我们需要在分布式开发中使用XML-RPC技术,那么该怎么办呢?

3.1 创建接口

using CookComputing.XmlRpc;

namespace interfaces
{
    public interface IMath
    {
        [XmlRpcMethod("Imath.add")]
        [return:XmlRpcReturnValue(Description="返回两个值加法的结果")]
        int Add(
            [XmlRpcParameter(Description="第一个参数")]
            int a,
            [XmlRpcParameter(Description="第二个参数")]
            int b);
    }
}

3.2 创建服务【需要添加CookComputing这个程序集,以及interfaces这个程序集引用】

using CookComputing.XmlRpc;

namespace Services
{
    [XmlRpcService(AutoDocumentation=true,Description="这是我的服务")]
    public class MathService:XmlRpcService,interfaces.IMath
    {
        #region IMath 成员

        int interfaces.IMath.Add(int a, int b)
        {
            return a + b;
        }

        #endregion
    }
}
        这里除了实现接口,不要忘记继承XmlRpcService这个类
        我们这里简单地把该服务宿主在一个网站里面,那么修改该web.config文件
        <httpHandlers>
            <add verb="*" type="Services.MathService" path="MathService.axd"/>
        </httpHandlers>

3.3 创建客户端

using System;
using CookComputing.XmlRpc;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "http://localhost:1500/MathService.axd";
            IMath mathservice = XmlRpcProxyGen.Create<IMath>();
            mathservice.Url = url;
            Console.WriteLine(mathservice.Add(100, 200));
            Console.Read();
        }
    }
    public interface IMath:IXmlRpcProxy
    {
        [XmlRpcMethod("Imath.add")]
        [return: XmlRpcReturnValue(Description = "返回两个值加法的结果")]
        int Add(
            [XmlRpcParameter(Description = "第一个参数")]
            int a,
            [XmlRpcParameter(Description = "第二个参数")]
            int b);
    }
}
        这里有一个关键,就是在客户程序中的那个接口要实现IXmlRpcProxy,否则是无法指定Url的。
        这个客户端代理接口中的XmlRpcMethod必须与服务端是对应的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值