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

来源:互联网 发布:java快速排序代码 递归 编辑:程序博客网 时间:2024/06/07 05:15

假定在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的通信过程

原创粉丝点击