JiveJdon Community Forums
在线84人   首页   主题总表   培训咨询   精华   查搜   注册    登陆
首页 » 论坛 » 项目工程开发经验谈
???en_US.forumThreadPrev.name??? 上一主题
  Go back to the topic 返回本主题   Go back to the topic listing返回主题列表
???en_US.forumThreadNext.name??? 下一主题
Go 总共有 3 回复 / 1
 发表新帖子   回复该主题贴
blues

悄悄话
发表文章: 74
注册时间: 2002年09月23日 17:07
xmlrpc walk through 2005年10月19日 21:27 到本帖网址 加入本帖到收藏夹 发送到手机 回复该主题
标签列表 webservice(17)      分布式计算(32)     
0.为什么整理xml rpc,并share
希望互通有无,实际上这些东西并不复杂,但大家的时间都有限。希望能共享。

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//////////////////////////////////

////////////////////////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//////////////////////////////////

////////////////////////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//////////////////////////////////
banq

悄悄话
发表文章: 9290
注册时间: 2002年08月03日 17:08
Re: xmlrpc walk through 2005年10月20日 11:50 到本帖网址 加入本帖到收藏夹 发送到手机 回复该主题
经常有人问:
客户端不使用浏览器如何办?
客户端可否使用Delphi或VB客户端?
客户端能否不采取从服务器拉的方式,而是由服务器推信息过来?
多层结构的C/S架构如何实现?

本文提出XML RPC这样解决方案,非常不错,本文是学习和理解XML RPC很好的教程,从代码和原理都适合亲自动手实验。
不过在J2EE中,Apache Axis等都已经整合了XML RPC,不必自己再另写Server端代码。

从XML RPC可以了解一下SOAP或者Web服务,都是一条路线发展过来的。

我设计的Jdon框架中也有RPC,不过是基于Object的,类似RMI,但是是Http协议,如果都是java,转换成XML浪费性能。

XML RPC的web服务将在SOA架构中大显身手,我想XML RPC和Web services以及SOAP都会在以后推出的SOA服务器中处于底层位置,可能无需我们来开发。

banq

悄悄话
发表文章: 9290
注册时间: 2002年08月03日 17:08
Re: xmlrpc walk through 2005年10月20日 12:27 到本帖网址 加入本帖到收藏夹 发送到手机 回复该主题
apache的web service开源与xml rpc相关项目:

http://ws.apache.org/

在XML世界,有两种方式实现RPC,一个是XML RPC;一个是SOAP。
XML-RPC 是一种比SOAP 更早的、简单的轻量级Web 服务技术。XML-RPC是 XML Web服务的鼻祖,大多数语言都有了标准的或已经可用的 XML-RPC 实现。

XML-RPC 要求不高,只是提出一个请求和处理信息的简单有效途径,
SOAP突破了XML-RPC限制,在XML-RPC上对XML信息格式更加优化和定制,这样开发者能够对发送的XML进一步规定细化,所以SOAP更适合Service服务这样相互调用(SOA)架构:

http://weblog.masukomi.org/writings/xml-rpc_vs_soap.htm

XML-RPC是一个用XML消息执行RPC的简单协议,服务请求使用XML来编码,并通过HTTP POST发送,XML响应被嵌入HTTP响应主体。

SOAP是在计算机之间交换信息的基于XML的协议,主要侧重于通HTTP传输RPC。它利用了XML的命名空间和XML模式(XML Schema)。

XML-RPC是启动web服务最容易的方法,在很多方面比SOAP更简单易用,但不同于SOAP的是,XML-RPC没有相应的服务Service描述语法,这妨碍了XML-RPC服务Service的自动调用。



banq

悄悄话
发表文章: 9290
注册时间: 2002年08月03日 17:08
Re: xmlrpc walk through 2005年10月23日 15:35 到本帖网址 加入本帖到收藏夹 发送到手机 回复该主题
一个比较好专门进行远程调用的开源框架:Crispy(10月23日在Sourceforge Framework排行中领先Jdon Framework前两名,排名第8,在看排名时发现的)
XML-RPC是远程调用的一种方式,WebService是使用JAX-RPC,现在存在各种各样不同的远程调用,还有:RMI,EJB的JNDI调用,我们要为每个远程服务写不同的调用代码,非常麻烦,无论Jdon框架/Spring/HiveMind等,都是试图通过下面形式解决服务调用:
MyService myService = (MyService)XXXX.getService();
目前版本在支持远程服务调用这方面,还没有CriSpy那样专业和全面,它基本支持SOA所支持大部分远程服务,CriSpy的远程服务调用形式非常类似上述调用,例如它的Web服务调用语句:


Properties prop = new Properties();
prop.put(Property.REMOTE_URL_AND_PORT, "http://localhost:9080/axis/services");
prop.put(Property.EXECUTOR_CLASS, JaxRpcExecutor.class.getName());

ServiceManager manager = new ServiceManager(prop);
Calculator calc = (Calculator) manager.createService(Calculator.class);
System.out.println(
"1 + 2 = " + calc.add(1, 2));


XML-RPC调用如下:


Properties prop = new Properties();
prop.put(Property.REMOTE_URL_AND_PORT,
"http://localhost:9090");
prop.put(Property.EXECUTOR_CLASS, XmlRpcExecutor.class.getName());

ServiceManager manager = new ServiceManager(prop);
Calculator calc = (Calculator) manager.createService(Calculator.class);
System.out.println(
"1 + 2 = " + calc.add(1, 2));


看看两种不同形式的调用,客户端代码几乎一致。

CriSpy还可应用在ESB,或者是JBI的客户端,胖客户端和服务器的通讯等。

Jdon框架也支持胖客户端和服务器,但只限于Java客户端,没有拓展到XML。

所幸的是CriSpy可以被嵌入Spring HiveMind, Jdon,CriSpy下一步打算是使用Pico来管理它的组件,我看和Jdon整合真是不错,还有liao的OBI,是一个组件集群框架,也可以和Jdon框架整合,使的Jdon框架的POJO组件可以有集群计算能力,那不是另外一个轻量EJB吗?

CriSpy网址:
http://sourceforge.net/projects/crispy/
这个主题有 3 回复 / 1Go
???en_US.forumThreadPrev.name??? 上一主题
  Go back to the topic 返回本主题   Go back to the topic listing返回主题列表    返回页首返回页首
???en_US.forumThreadNext.name??? 下一主题
热点TAG: AOP cache 缓存 DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Seam Spring Struts
google yahoo 新浪ViVi 365Key网摘 天极网摘 CSDN网摘 添加到百度搜藏 POCO网摘 博采网摘
查询本论坛内 回复超过的热门帖子
     回复该主题贴
标题
 
粗体 斜体 下划线 插入图片 插入代码 插入url链接 插入附件
内容
 

手机阅读 add to google add to yahoo
解惑之道在J道 ,打造中国最具影响力的的企业软件社区
OpenSource JIVEJDON v3.0 Powered by JdonFramework Code © 2002-08 jdon.com
anti spam