基于系统的分布式对象是通过定义好的接口来隔离客户端请求和服务器端服务的对象集。数据请求和执行是分开的,这是C/S模式与分布式模式的主要区别。 在一个分布式模型里,客户端发送消息给一个对象,这个对象判断消息决定哪种服务执行。服务或者方法,SELECTION被对象或者代理来执行。RMI和CORBA就是这个模型的例子。 RMI
RMI是能使你很容易地开发分布市对象的系统。RMI比SOCKETS开发容易地多,不需要定义协议。用RMI,开发者会认为调用本地类的本地方法,实际上是从远程传输,翻译,并把结果传递到本地。 RMI应用起步
开发RMI,包括以下几个步骤:1 定义一个远程接口2 应用远程接口3 服务器端开发4 客户端开发5 生成骨干代码,启动RMI注册,服务器,客户端 下面我们讲述每一步的具体实现。 例子:文件传输应用 允许传输任何类型的文件到远程主机。第一步定义描述方法的远程接口。定义远程接口代码一是下载文件的远程接口。接口FileInterface 提供了一个下载文件的方法,返回文件的字节集。 Code Sample 1: FileInterface.java import java.rmi.Remote;
import java.rmi.RemoteException;
 
public interface FileInterface extends Remote {
   public byte[] downloadFile(String fileName) throws
   RemoteException;
}
  注意:为了客户端能装载包含远程接口的远程对象,接口必须定义为Public必须扩展Remote接口,为了实现远程对象接口里的每个方法必须抛出RemoteException异常 应用远程接口
下一步是实现接口FileInterface,一个简单的应用在代码二。注意为了实现接口FileInterface,类FileImpl必须扩展UnicastRemoteObject。这说明类FileImpl创建一个单一,不能复制的通过TCP传输的RMI对象, Code Sample 2: FileImpl.java import java.io.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
 
public class FileImpl extends UnicastRemoteObject
  implements FileInterface {
 
   private String name;
 
   public FileImpl(String s) throws RemoteException{
      super();
      name = s;
   }
 
   public byte[] downloadFile(String fileName){
      try {
         File file = new File(fileName);
         byte buffer[] = new byte[(int)file.length()];
         BufferedInputStream input = new
      BufferedInputStream(new FileInputStream(fileName));
         input.read(buffer,0,buffer.length);
         input.close();
         return(buffer);
      } catch(Exception e){
         System.out.println("FileImpl: "+e.getMessage());
         e.printStackTrace();
         return(null);
      }
   }
}
 服务器端开发
 第三步是开发服务器端,有三个步骤:1 创建RMISecurityManager实例并安装它2 创建一个远程对象的实例3 用RMI注册对象。 Code Sample 3: FileServer.java import java.io.*;
import java.rmi.*;
 
public class FileServer {
   public static void main(String argv[]) {
      if(System.getSecurityManager() == null) {
         System.setSecurityManager(new RMISecurityManager());
      }
      try {
         FileInterface fi = new FileImpl("FileServer");
         Naming.rebind("//127.0.0.1/FileServer", fi);
      } catch(Exception e) {
         System.out.println("FileServer: "+e.getMessage());
         e.printStackTrace();
      }
   }
}
 这句 Naming.rebind("//127.0.0.1/FileServer", fi) 说明RMI 注册是运行在缺省端口1099。如果RMI注册是在其它端口,此句应改为: Naming.rebind("//127.0.0.1:4500/FileServer", fi) 客户端开发
下一步就是开发客户端。客户端远程调用远程接口定义的任何方法。为了实现,客户端必须先获得RMI注册的远程对象的实例。一旦获得,下载文件方法就别调用。如代码4。这个应用中,客户端接收两个命令行参数。 Code Sample 4: FileClient.java import java.io.*; 
import java.rmi.*;
 
public class FileClient{
   public static void main(String argv[]) {
      if(argv.length != 2) {
        System.out.println("Usage: java FileClient fileName machineName");
        System.exit(0);
      }
      try {
         String name = "//" + argv[1] + "/FileServer";
         FileInterface fi = (FileInterface) Naming.lookup(name);
         byte[] filedata = fi.downloadFile(argv[0]);
         File file = new File(argv[0]);
         BufferedOutputStream output = new
           BufferedOutputStream(new FileOutputStream(file.getName()));
         output.write(filedata,0,filedata.length);
         output.flush();
         output.close();
      } catch(Exception e) {
         System.err.println("FileServer exception: "+ e.getMessage());
         e.printStackTrace();
      }
   }
}
 运行这个应用 为了运行这个应用,我们必须先生成骨干码,然后编译服务器端,客户端代码,RMI注册,最后开始应用。为了生成骨干码,我们用RMIC命令:命令行: rmic FileImpl 将生成两个文件: FileImpl_Stub.class 和 FileImpl_Skel.class. 客户端代理和服务端骨干。下一步,编译SERVER,CLIENT代码最后,开始RMI注册,运行。 命令行> rmiregistry portNumber 注册完成后,就可以开始服务器端应用。如果应用了RMI安全管理,你需要一个安全策略来处理。下面就是一个简单的security policy: grant {
   permission java.security.AllPermission "", "";
};
 注意:这只是一个简单的安全策略,如果比较重要的应用,你需要用更严格的安全策略。 拷贝所有的类除了客户端类。确认安全策略在policy.txt后,用下面命令开始服务器端应用。命令行> java -Djava.security.policy=policy.txt FileServer 为了在不同的机器开始客户端应用,你需要拷贝 (FileInterface.class) 和(FileImpl_Stub.class).命令行> java FileClient fileName machineName