您的位置:首页 > 其它

在远程方法调用中运用反射机制

2009-11-27 10:30 525 查看
假定在SimpleServer服务器端创建了一个HelloServiceImpl对象,它具有getTime()和echo()方法。HelloServiceImpl类实现了HelloService接口。如例程10-6和例程10-7所示分别是HelloService接口和HelloServiceImpl类的源程序。

例程10-6 HelloService.java
package remotecall;
import java.util.Date;
public interface HelloService{
public String echo(String msg);
public Date getTime();
}
例程10-7 HelloServiceImpl.java
package remotecall;
import java.util.Date;
public class HelloServiceImpl implements HelloService{
public String echo(String msg){
return "echo:"+msg;
}
public Date getTime(){
return new Date();
}
}
SimpleClient客户端如何调用服务器端的HelloServiceImpl对象的getTime()和echo()方法呢?显然,SimpleClient客户端需要把调用的方法名、方法参数类型、方法参数值,以及方法所属的类名或接口名发送给SimpleServer,SimpleServer再调用相关对象的方法,然后把方法的返回值发送给SimpleClient。
为了便于按照面向对象的方式来处理客户端与服务器端的通信,可以把它们发送的信息用Call类(如例程10-8所示)来表示。一个Call对象表示客户端发起的一个远程调用,它包括调用的类名或接口名、方法名、方法参数类型、方法参数值和方法执行结果。
例程10-8 Call.java
package remotecall;
import java.io.*;
public class Call implements Serializable{
private String className; //表示类名或接口名
private String methodName; //表示方法名
private Class[] paramTypes; //表示方法参数类型
private Object[] params; //表示方法参数值
//表示方法的执行结果
//如果方法正常执行,则result为方法返回值,如果方法抛出异常,那么result为该异常。
private Object result;

public Call(){}
public Call(String className,String methodName,Class[] paramTypes,
Object[] params){
this.className=className;
this.methodName=methodName;
this.paramTypes=paramTypes;
this.params=params;
}

public String getClassName(){return className;}
public void setClassName(String className){this.className=className;}
public String getMethodName(){return methodName;}
public void setMethodName(String methodName){this.methodName=methodName;}
public Class[] getParamTypes(){return paramTypes;}
public void setParamTypes(Class[] paramTypes){this.paramTypes=paramTypes;}
public Object[] getParams(){return params;}
public void setParams(Object[] params){this.params=params;}
public Object getResult(){return result;}
public void setResult(Object result){this.result=result;}
public String toString(){
return "className="+className+" methodName="+methodName;
}
}
SimpleClient调用SimpleServer端的HelloServiceImpl对象的echo()方法的流程如下。
(1)SimpleClient创建一个Call对象,它包含了调用HelloService接口的echo()方法的信息。
(2)SimpleClient通过对象输出流把Call对象发送给SimpleServer。
(3)SimpleServer通过对象输入流读取Call对象,运用反射机制调用HelloServiceImpl对象的echo()方法,把echo()方法的执行结果保存到Call对象中。
(4)SimpleServer通过对象输出流把包含了方法执行结果的Call对象发送给SimpleClient。
(5)SimpleClient通过对象输入流读取Call对象,从中获得方法执行结果。
如例程10-9和例程10-10所示分别是SimpleServer和SimpleClient的源程序。
例程10-9 SimpleServer.java
package remotecall;
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
public class SimpleServer {
private Map remoteObjects=new HashMap(); //存放远程对象的缓存

/** 把一个远程对象放到缓存中 */
public void register(String className,Object remoteObject){
remoteObjects.put( className,remoteObject);
}
public void service()throws Exception{
ServerSocket serverSocket = new ServerSocket(8000);
System.out.println("服务器启动.");
while(true){
Socket socket=serverSocket.accept();
InputStream in=socket.getInputStream();
ObjectInputStream ois=new ObjectInputStream(in);
OutputStream out=socket.getOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(out);
Call call=(Call)ois.readObject(); //接收客户发送的Call对象
System.out.println(call);
call=invoke(call); //调用相关对象的方法
oos.writeObject(call); //向客户发送包含了执行结果的Call对象

ois.close();
oos.close();
socket.close();
}
}
public Call invoke(Call call){
Object result=null;
try{
String className=call.getClassName();
String methodName=call.getMethodName();
Object[] params=call.getParams();
Class classType=Class.forName(className);
Class[] paramTypes=call.getParamTypes();
Method method=classType.getMethod(methodName,paramTypes);
Object remoteObject=remoteObjects.get(className); //从缓存中取出相关的远程对象
if(remoteObject==null){
throw new Exception(className+"的远程对象不存在");
}else{
result=method.invoke(remoteObject,params);
}
}catch(Exception e){result=e;}
call.setResult(result); //设置方法执行结果
return call;
}
public static void main(String args[])throws Exception {
SimpleServer server=new SimpleServer();
//把事先创建的HelloServiceImpl对象加入到服务器的缓存中
server.register("remotecall.HelloService",new HelloServiceImpl());
server.service();
}
}
例程10-10 SimpleClient.java
package remotecall;
import java.io.*;
import java.net.*;
import java.util.*;
public class SimpleClient {
public void invoke()throws Exception{
Socket socket = new Socket("localhost",8000);
OutputStream out=socket.getOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(out);
InputStream in=socket.getInputStream();
ObjectInputStream ois=new ObjectInputStream(in);
//Call call=new Call("remotecall.HelloService","getTime",
new Class[]{},new Object[]{});
Call call=new Call("remotecall.HelloService","echo",
new Class[]{String.class},new Object[]{"Hello"});
oos.writeObject(call); //向服务器发送Call对象
call=(Call)ois.readObject(); //接收包含了方法执行结果的Call对象
System.out.println(call.getResult());
ois.close();
oos.close();
socket.close();
}
public static void main(String args[])throws Exception {
new SimpleClient().invoke();
}
}
先运行命令“java remotecall.SimpleServer”,再运行命令“java remotecall. SimpleClient”,SimpleClient端将打印“echo:Hello”。该打印结果是服务器端执行HelloServiceImpl对象的echo()方法的返回值。如图10-1所示显示了SimpleClient与SimpleServer的通信过程。



图10-1 SimpleClient与SimpleServer的通信过程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: