动态回调基于xml的远程过程调用
摘要
java反射机制为使用xml-rpc(xml-based remote procedure call,基于xml的远程过程调用)远程过程调用提供了一种简便又高效的实现方法,这种方法隐蔽掉了一些远程过程调用过程中的复杂操作。在这篇文章里,stephan maier展示给你如何从反射包中使用一些类去包装xml-rpc去调用远程接口:proxy类,array类, 和beaninfo类。这篇文章也将要讨论这种方法的多重实现和在rmi(remote method invocation,远程方法调用)中可反射方法的使用。
因为它作为远程方法调用的一个简单协议,人们偶尔关注基于xml的远程过程调用(xml-rpc)。它易于使用,又着可以运用的实现-apache xml-rpc。
如果是一个小应用程序或应用程序中使用有限数量的远程过程,那么不应该趋向于正式地定义远程过程的名字和方法声明,取而代之,应该直接使用xml-rpc。甚至,应用程序规模增大和远程接口数量增加,将可发现对远程方法和数据对象必要的约定必定是一种莫名的一致。在这篇文章里,将展示java提供的所有需要去实现的定义远程接口和访问远程方法:过程,使用java接口定义的过程签名,和使用xml-rpc的远程过程调用-这种调用把一个通信信道的两侧封装成仅仅是接口和相对的数据对象。
本文也展示当给定的描述远程过程和数据的java接口构建与 javabean规范一致,可以使用java反射机制,把反射机制和javabean整合使用可以透明地调用远程方法,轻松地在xml-rpc数据类型和java数据类型之间进行转换。
实际中隐藏复杂性是个好的事情。无需说,不是所有的复杂性能或者应该被隐藏。针对分布式计算,这个观点已经在“分布式计算笔记”有了个著名的论著。(sun microsystems,1994.11)。本文中展现的框架不特意去隐藏分布式计算的复杂性,但这个框架帮助使用者减少在调用远程过程时的繁琐。简单点说,本文只讨论并发远程过程调用,热心的读者可以自己去研究觳皆冻坦痰饔谩?
xml-rpc可以被看作rpc跨soap协议的一个简化。扩展点说,本文所讨论的这个简易框架必须被认为soap引擎的简化版本,就像axis。本文主要以教学位目标:希望展示在目前的xml-rpc框架上层是怎样通过反射来建立一个简化的xml-rpc引擎。这些帮助读者理解相似且更复杂的其他协议的引擎的内部实现机理,或怎样应用反射去解决复杂问题。一个rpc引擎必须在soap引擎可实现的环境中使用,就好比中间件控件不可用,那么应用程序就不能通过web服务器发布给广大用户。roy miller’s “xml-rpc java 编程”对这个作了很好的解释。
在本文中,使用xml-rpc的apache组件去安装这个框架。读者不需奥区知道xml-rpc,也不需要理解apache xml-rpc框架,就是只有一个基本的了解都能使你理解下面的讲述。本文重点放在框架内部精确的运作机理,但不涉及协议的细节。
版权声明:任何获得matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:steven_guo(作者的blog:http://blog.matrix.org.cn/page/steven_guo)
原文:http://www.matrix.org.cn/resource/article/44/44437_xml-rpc.html
关键字:xml-rpc;reflective
消除习惯
有时候,我更喜欢非传统的编程。谈到这点,我必须使你确信,我不是一个总打破旧习俗的人,我不反对好的编程习惯;恰恰与此完全相反。“非传统”在这里主要表明我喜欢去避免程序中到处的定义字符串,而且这些代码可以在可编程的api里定义。考虑下面代码片断。
代码1. 调用远程过程
vector paras = new vector();
paras.add("herbert");
object result = client.execute("app.personhome.getname", paras);
person person = ((personhome)invocator.getproxy(personhome.class)).getperson("herbert");
public static object getproxy(class iftype) {
if (!iftype.isinterface()) {
throw new assertionerror("type must be an interface");
}
return proxy.newproxyinstance(invocator.class.getclassloader(),
new class[]{iftype}, new xmlrpcinvocationhandler(iftype));
} public interface invocationhandler {
public object invoke(object proxy, method method, object[] args) throws throwable;
} private static class xmlrpcinvocationhandler implements invocationhandler {
private class type;
public xmlrpcinvocationhandler(class iftype) {
this.type = iftype;
}
public object invoke(object proxy, method method, object[] args) throws throwable {
xmlrpcclient client = getclient(); // get a reference to the client
vector paras = null; // this will hold the list of parameters
if (args != null){
paras = new vector();
for (int i = 0; i < args.length; i++) {
paras.add(valueconverter.convertfromtype(args[i]));
}
}
else{
paras = new vector(); // the vector holding the parameters must not be null
}
class rettype = method.getreturntype();
object ret = client.execute(type.getname() + '.' + method.getname(), paras);
return valueconverter.converttotype(ret, rettype);
}
}
protected static xmlrpcclient getclient() throws malformedurlexception {
return new xmlrpcclient("localhost", 8080);
}
public static object convertfromtype(object obj) throws illegalargumentexception,
illegalaccessexception, invocationtargetexception, introspectionexception {
if (obj == null) {
return null;
}
class type = obj.getclass();
if (type.equals(integer.class)
type.equals(double.class)
type.equals(boolean.class)
type.equals(string.class)
type.equals(date.class)) {
return obj;
else if (type.isarray() && type.getcomponenttype().equals(byte.class)) {
return obj;
}
else if (type.isarray()) {
int length = array.getlength(obj);
vector res = new vector();
for (int i = 0; i < length; i++) {
res.add(convertfromtype(array.get(obj, i)));
}
return res;
}
else {
hashtable res = new hashtable();
beaninfo info = introspector.getbeaninfo(type, object.class);
propertydescriptor[] props = info.getpropertydescriptors();
for (int i = 0; i < props.length; i++) {
string propname = props[i].getname();
object value = null;
value = convertfromtype(props[i].getreadmethod().invoke(obj, null));
if (value != null) res.put(propname, value);
}
return res;
}
}
public static object converttotype(object object, class type) throws illegalargumentexception,
illegalaccessexception, invocationtargetexception, introspectionexception, instantiationexception {
if (type.equals(int.class)
type.equals(double.class)
type.equals(boolean.class)
type.equals(string.class)
type.equals(date.class)) {
return object;
}
else if (type.isarray() && type.getcomponenttype().equals(byte.class)) {
return object;
}
else if (type.isarray()) {
int length = ((vector) object).size();
class comptype = type.getcomponenttype();
object res = array.newinstance(comptype, length);
for (int i = 0; i < length; i++) {
object value = ((vector) object).get(i);
array.set(res, i, converttotype(value, comptype));
}
return res;
}
else {
object res = type.newinstance();
beaninfo info = introspector.getbeaninfo(type, object.class);
propertydescriptor[] props = info.getpropertydescriptors();
for (int i = 0; i < props.length; i++) {
string propname = props[i].getname();
if (((hashtable) object).containskey(propname)) {
class proptype = props[i].getpropertytype();
props[i].getwritemethod().
invoke(res, new object[]
{ converttotype(((hashtable) object).get(propname), proptype)});
}
}
return res;
}
}
public class server {
private webserver webserver = null;
public void start() {
webserver = new webserver(8080);
webserver.addhandler
(personhome.class.getname(),
new handler(personhome.class,
new personhomeimpl()));
webserver.setparanoid(false);
webserver.start();
}
public void stop() {
webserver.shutdown();
webserver = null;
}
private static class handler implements xmlrpchandler {
private object instance;
private class type;
public handler(class iftype, object impl) {
if (!iftype.isinterface()) {
throw new assertionerror("type must be an interface");
}
if (!iftype.isassignablefrom(impl.getclass())) {
throw new assertionerror("handler must implement interface");
}
this.type = iftype;
this.instance = impl;
}
public object execute(string method, vector arguments) throws exception {
string mname = method.substring(method.lastindexof('.') + 1);
method[] methods = type.getmethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getname().equals(mname)){
try {
object[] args = new object[arguments.size()];
for (int j = 0; j < args.length; j++) {
args[j] = valueconverter.converttotype
(arguments.get(j), methods[i].getparametertypes()[j]);
}
return valueconverter.convertfromtype(methods[i].invoke(instance,args));
}
catch (exception e) {
if (e.getcause() instanceof xmlrpcexception){
throw (xmlrpcexception)e.getcause();
}
else{
throw new xmlrpcexception(-1, e.getmessage());
}
}
}
}
throw new nosuchmethodexception(mname);
}
}
public static void main(string[] args){
server server = new server();
system.out.println("starting server...");
server.start();
try {
thread.sleep(30000);
}
catch (interruptedexception e) {
e.printstacktrace();
}
system.out.println("stopping server...");
server.stop();
}
} public class myclassbeaninfo extends simplebeaninfo {
public propertydescriptor[] getpropertydescriptors() {
try {
beaninfo superinfo = introspector.getbeaninfo(myclass.class.getsuperclass());
list list = new arraylist();
for (int i = 0; i < superinfo.getpropertydescriptors().length; i++) {
list.add(superinfo.getpropertydescriptors()[i]);
}
//
list.add(new propertydescriptor("myproperty", myclass.class));
//
return (propertydescriptor[])list.toarray(new propertydescriptor[list.size()]);
} catch (introspectionexception e) {
return null;
}
}
} public class myclassbeaninfo extends simplebeaninfo {
public propertydescriptor[] getpropertydescriptors() {
try {
beaninfo infobyreflection = introspector.getbeaninfo(myclass.class,
introspector.ignore_all_beaninfo); propetydescriptor allproperies =
infobyreflection.getpropertydescriptors();
return filter(allproperies);
} catch (introspectionexception e) {
return null;
}
}
protected propertydescriptor[] filter(propertydescriptor[] props){
// remove properties which must not be exposed
}
} module partner;
exception nopartnerexception < 123 : "no partner found" >;
struct partner {
int id;
string name;
int age;
date birthday;
};
interface partnerhome {
partner getpartner(int id) throws nopartnerexception;
partner[] findpartner(string name, date bday) throws nopartnerexception;
};
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器