rmi的初体验!

来源:互联网 发布:linux创建用户组 编辑:程序博客网 时间:2024/06/11 08:12
RMI(Remote method Invocation),中文意思为:远端函数调用。允许java程序调用远程对象的方法,就好像使用本地对象的方法一样。

RMI的有点如下:
1:面向对象,RMI可以将完整的对象作为参数传递或者返回,而不仅仅是基本的数据类型。
2:   安全,RMI使用java内置的安全管理机制,保证下载程序的安全性。
3:简单而且易于编写,和socket机制相比,RMI屏蔽了底层的实现细节,编写程序时无需考虑传输协议。同时RMI可以使用http进行通信,从而可以跨过防火墙和代理服务器进行远程通信。
4:跨平台。RMI是java的一部分,具有“编写一次,到处运行”的优点。
5:并行计算,RMI采用多线程处理方法,服务器利用java线程并行处理客户端的请求。

   Client                  Server
      
    
     
StubsSkelton
Remote reference Layer
Transport



在RMI中,调用远程对象的对象被称为客户机对象(Client Object)而远程对象被称为服务器对象(Server Object),同时引入了两种特殊类型对象,存根(stub)和框架(Skelton).存根是代表远程对象的客户端对象,它和远程对象具有相同的接口或方法列表,当客户端调用远程对象时,实际上是由相应的存根对象代理完成,存根通过对象处理远方所有细节,存根通过RMI基础结构将请求转发到远程对象,最后有远程对象执行请求。在服务器端,框架对象处理“远方”的所有细节,因此实际的远程对象不必担心这些细节。也就是说,完全可以像编写本地对象一样来编写远程对象。框架将远程对象从RMI基础结构分离开来。

     到此,我们应该对RMI的基本工作原理有个初步的了解,那么现在让我们开始编写一个实际的RMI应用程序吧!RMI应用程序的编写分为一下几步!

第一步:编写远端接口。
要产生远端接口,必须依循以下规则:
1。远端接口必须被声明为public,否则客户端在试着装在“实现出远端接口”的远端对象时会收到错误消息。

2。远端对象必须继承java.rmi.Remote这一接口。

3。每个远端接口中的函数,除了自定义异常外,还必须抛出java.rmi.RemoteException.

4.作为引数或返回值的远端对象,都必须被声明为远端接口,而非实际class.

现在让我们开始编写一个取得系统时间的远端接口。如下:
     package net.xiaobo.remoteserver;
import java.util.*;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface HelloRemote extends Remote{
 public Date getTime() throws RemoteException;
}
以上接口均符合以上规定。

第二步:实现出远端接口。
服务器必须内含一个继承自UnicastRemoteObject并实现出远端接口的class,这个class也可以拥有额外的函数,但只有在远端接口中定义的函数才可为客户端调用。如下:
package net.xiaobo.remoteserver;

import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.util.*;

public class HelloRemoteImp extends UnicastRemoteObject implements HelloRemote{
 public Date getTime()throws RemoteException{
  return new Date();
 }
 public HelloRemoteImp()throws RemoteException{
 }
 public static void main(String args[])throws Exception{
  System.setSecurityManager(new RMISecurityManager());
  HelloRemoteImp hri=new HelloRemoteImp();

  Naming.bind("/HelloRemoteImp",hri);
  System.out.println("Succeed in binding,now ready to do time");
 }
}


第三步:(可由可无,我自己的习惯,大家也可以在%java_home/jre/lib/security/java.policy中配置)
编写权限文件,与上述文件在同一个目录下。名位policy.
/*
 * Only grant permissions to the local class path (the current directory).
 */
grant codeBase "file:." {

    permission java.net.SocketPermission "*:1024-", "connect,accept";


};


第四步:运行以上文件,命令如下:
      javac -d . HelloRemote.java         该命令产生目录为net/xiaobo/remoteserver/HelloRemote.class
      javac -d . HelloRemoteImp.java   该命令产生目录为net/xiaobo/remoteserver/HelloRemoteImp.class
      rmic  -d .  HelloRemoteImp          该命令产生目录为net/xiaobo/remoteserver/HelloRemoteImp_Stub.class
                                                                                          net/xiaobo/remoteserver/HelloRemoteImp_Skelton.class
      

第五步:启动服务器并设定注册薄进行绑定。命令如下:

     rmiregistry (启动注册薄服务器)
     java -Djava.security.policy=policy    net.xiaobo.remoteserver.HelloRemoteImp
    该命令-Djava.security.policy=policy指定java解释程序用指定的policy文件设定权限,同时启动服务器,进行远端对象的绑定。即执行

                       Naming.bind("/HelloRemoteImp",hri);
该代码会将服务名称HelloRemoteImp和对象hri进行绑定。便于在客户端查询远端对象。如果运行成功,则会出现一下提示:Succeed in binding,now ready to do time

第六步:编写客户端代码进行测试。
代码如下:

package net.xiaobo.remoteclient;
import net.xiaobo.remoteserver.*;
import java.rmi.*;
import java.rmi.registry.*;

public class DisplayTime{
 public static void main(String[] args)throws Exception{
        if(System.getSecurityManager() == null){
  System.setSecurityManager(new RMISecurityManager());
  }
  HelloRemote t=(HelloRemote)Naming.lookup("/HelloRemoteImp");
  System.out.println(t.getTime());
 }
}

该代码中运用Naming.lookup("/HelloRemoteImp")来取得一个远程对象的引用,此时我们可以将t看做是本地对象一样,来操作它的方法。
现在在命令行下执行一下命令:
            javac -d . DisplayTime.java
  在执行如下命令时请确保第五步运行正常,并且服务器已经启动(该命令行窗口没有反应,这是我的状况!)

            java -Djava.security.policy=policy  net.xiaobo.remoteclient.DisplayTime

如果运行正常就会出项一下结果:
  Mon Feb 21 19:16:32 CST 2005

至此,我对rmi的初步学习也一个成功的例子告终,以上均是我的实际操作,其中在所难免有很多不足,我相信在今后的学习中自己会有更多的了解。

原创粉丝点击