`
marb
  • 浏览: 412095 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多

RMI是Java对象进行远程访问的一种规范——也就是说,从Java虚拟机(Java Virtual Machine,JVM)而不是特定对象的主机访问。这些对象可能位于拥有JVM的同一个物理主机上,或者位于其他计算机上,并通过某个网络连接到宿主主机(服务器)。规范包括这些对象进行编码的规则,如何定位对象,如何远程调用,方法的参数和计算结果如何在JVM之间传递。RMI的缺省实现是JRMP(Java Remote Method Protocol),这是一个百分之百的Java实现。此外,RMI也可以使用其它的协议,例如IIOP。

RMI可利用标准Java本机方法接口JNI与现有的和原有的系统相连接。RMI还可利用标准JDBC包与现有的关系数据库连接。RMI/JNI和RMI/JDBC相结合,可帮助您利用RMI与目前使用非Java语言的现有服务器进行通信,而且在您需要时可扩展Java在这些服务器上的使用。RMI可帮助您在扩展使用时充分利用Java的强大功能。

下面我们通过一个例子,来说明怎么构建RMI应用。我们写一个例子,通过RMI获取服务器端的时间。下面是构造这个例子的全部过程。

首先定义一个接口,因为RMI的调用都是通过接口进行的,因此我们只能定义接口。代码如下:

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
* 定义一个远程接口,这个接口应该继承Remote
* @author Dirac
*/
public interface PerfectTime extends Remote
{
/**
* 因为这个方法是远程调用的,所以它应该抛出RemoteException
* @param param
* @return
* @throws RemoteException
*/
String getPerfectTime(String param) throws RemoteException;
}

 

第二步,给出具体实现,这里为了增加一些趣味,我们加入了一个名字,并把时间格式化成我们所习惯的格式,然后返回给客户。这个实现和普通类没有什么区别,只是需要继承一个特殊的类:

public class PerfectTimeImpl extends UnicastRemoteObject implements PerfectTime
{
private static final long serialVersionUID = 1793177637034935906L;
String name = "";
public PerfectTimeImpl(String name) throws RemoteException
{
this.name = name;
}

/**
* 返回的字符串中包含了服务器端的时间
*/
public String getPerfectTime(String param) throws RemoteException
{
return param + ": " + name + " is " + new SimpleDateFormat("yyyy年MM月dd
日HH时mm分ss秒SSS毫秒").format (new Date(System.currentTimeMillis()));
}
}

 

我们还可以通过继承RemoteServer来实现这个类,但是需要自己将它导出,方法是在构造函数中调用 UnicastRemoteObject.exportObject(this, 1099),第二个参数是要绑定的端口号。这里之所以没有显式导入,是因为UnicastRemoteObject已经为我们做了这步工作。

第三步,生成远程接口实现对应的stub,这是通过JDK自带的rmic实现的,命令如下:
rmic cn.zxm.rmi.PerfectTimeImpl

生成的stub对应的文件名是PerfectTimeImpl_Stub。我们可以在rmic后面跟-keep参数,保留生成的stub源码,这实际上是PerfectTimeImpl的代理,客户端调用的实际上就是这个stub。

第四步,在服务器端绑定这个远程对象,代码如下:

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;

/**
* @author Dirac
*/
public class PerfectTimeServer
{
public static void main(String [] agrs) throws RemoteException
{
try
{
//服务器端注册远程对象
PerfectTimeImpl p1 = new PerfectTimeImpl ("Black Stone");
PerfectTimeImpl p2 = new PerfectTimeImpl ("Anders Heijlsberg");
Naming.rebind ("p1", p1);
Naming.rebind ("p2", p2);
//获得注册的名字列表,并打印出来
String[] list = Naming.list("");
for(int i = 0; i < list.length; i++)
{
System.out.println("list[" + (i + 1) + "]=" + list[i]);
}
}
catch(MalformedURLException mue)
{
mue.printStackTrace ();
}
}
}

 

第五步,编写客户端调用代码,代码如下:

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;

/**
* @author Dirac
*/
public class PerfectTimeClient
{
public static void main(String [] args)
{
try
{
//客户端获取远程接口
PerfectTime p1 = (PerfectTime)Naming.lookup ("rmi://localhost:1099/p1");
PerfectTime p2 = (PerfectTime)Naming.lookup ("rmi://localhost:1099/p2");
//调用远程接口的方法
System.out.println (p1.getPerfectTime ("p1"));
System.out.println (p2.getPerfectTime ("p2"));
}
catch(RemoteException re)
{
re.printStackTrace ();
}
catch(MalformedURLException mue)
{
mue.printStackTrace ();
}
catch(NotBoundException nbe)
{
nbe.printStackTrace ();
}
}
}

 
第六步,设置CLASSPATH变量,方式是在命令行中使用命令set CLASSPATH=类路径,比如我的类路径是E:\study\rmi\classes,那么命令如下:
set CLASSPATH=E:\study\rmi\classes
这一步是必须的,不然向RMI注册机注册的时候会找不到stub。
第七步,启动RMI注册机,启动它的命令也是通过JDK自带的工具完成的,它和javac等工具位于一个目录下,命令如下:
start rmiregistry
start表示另起一个命令行窗口,新窗口和现在的命令行窗口共享同样的设置,比如上面的CLASSPATH。
第八步,启动服务器注册程序,命令如下:
start java cn.zxm.rmi.PerfectTimeServer
第九步,启动客户端调用程序,命令如下:
java cn.zxm.rmi.PerfectTimeClient
输出如图1:

图1 RMI客户端调用结果

部署时候需要注意的是,客户端都应该包含接口和实现对应的stub,其它的则不是必需的。
注册远程接口的时候,如果抛出ClassNotFound stub这样的错误,可能的原因,一是没有手工设置CLASSPATH,二是PATH变量当中,包含了多个JDK或者JRE的bin路径,这两个错误往往很难找,需要格外的注意。

除了在客户端直接部署stub外,还有一种方式,是通过网络获取。比如我把stub放在http://www.zxm.net:8081/order/perfect/下,当然要包含完整的包结构,stub这个例子中stub实际上位于http://www.zxm.net:8081/order/perfect/cn/zxm/rmi/下。客户端调用的方式如下:

java -Djava.rmi.server.codebase=http://www.zxm.net:8081/order/perfect/
cn.zxm.rmi.PerfectTimeClient

注意URL后面的/不可省略。由于从远程加载类,因此涉及到安全问题,java使用许可的方式,来保证安全。这是通过培植一个policy文件实现的,policy文件的配置很麻烦,我们这里由于是测试,不涉及安全问题,因此我们给它全部的许可,许可文件命名为server.policy,和PerfectTimeClient放在一个目录下,server.policy的内容如下:

grant{
    permission java.security.AllPermission;
}

然后,我们需要在客户端手工加载这个文件,并为客户端安装一个安全管理器,代码如下:

System.setProperty ("java.security.policy",
PerfectTimeClient.class.getResource ("server.policy").toString ());
System.setSecurityManager(new RMISecurityManager());

这样我们就可以使用动态类加载功能加载服务器上的stub文件了。

分享到:
评论

相关推荐

    【Java RMI介绍以及编写Demo】

    NULL 博文链接:https://gaojingsong.iteye.com/blog/2341692

    RMI规范 RMI详细介绍

    RMI 规范 RMI 详细介绍 共10章

    java rmi详细介绍介绍

    java rmi详细介绍介绍java rmi详细介绍介绍java rmi详细介绍介绍java rmi详细介绍介绍

    rmi接口技术详细介绍文档

    一份很全的介绍rmi基本原理,以及如何使用rmi,以及使用过程中需要注意的事项,非常不错的文档

    分布式实验报告RMI.docx

    本实验报告主要介绍了 Java RMI(Remote Method Invocation,远程方法调用)的基本概念和实现步骤。RMI 是一种分布式对象通讯机制,允许运行在一个 Java 虚拟机的对象调用运行在另一个 Java 虚拟机上对象的方法。 ...

    Weblogic Server与RMI

    Weblogic Server与RMI RMI的使用介绍

    java rmi详细介绍.doc

    java rmi详细介绍

    Spring Rmi使用文档

    Spring Rmi的使用,对Spring RMI进行全访问的介绍,并介绍了其中的源代码部分

    rmi 例子和详细介绍的ppt

    rmi 详细介绍 和 web应用实例(包含rimserver和rmiclient两个工程)

    rmi入门学习,实用的小例子

    描述java rmi的实用方式,有实用简单的入门介绍,很容易理解!!!

    JDK5新版RMI编程指南

    JDK5中,RMI技术已经得到了重大更新。现在使用JDK提供的RMI类,可以相当简单的发布RMI服务! 在JDK5发布之前,使用RMI是一件非常繁琐的事情。甚至很多程序员把EJB... 本文详细介绍了怎样使用JDK5新版的RMI进行开发!

    RMI:远程方法调用(RMI)简介

    RMI介绍该项目最初是作为在2015年秋季的Java课程中在Java中使用RMI的示例项目而编写的。安装$ mvn install$ java -Djava.security.policy=RMI-Server/server.policy -jar RMI-Server/target/RMI-Server-1.0.jar$ ...

    乳化液泵站RMI与KAMAT比较分析

    介绍了目前国内市场占有率较高的KAMAT泵站和RMI泵站的整体结构,从减速系统、液力系统、润滑系统、保护系统、控制系统等方面对其关键技术进行了全面的比较和分析,总结了各自的优缺点,并指出各自的改进方向:对于...

    RMI.rar_rmi

    这是一篇介绍RMI的入门性文档,里面包含了几个简单例子,对于入门有很大的帮助

    JAVA RMI规范

    详细介绍了JAVA RMI 的知识,不可多得的文档。长达60页,很详尽。对于java远程调用和分布式开发很有帮助。

    Java RMI详细介绍及简单实例

    主要介绍了Java RMI详细介绍及简单实例的相关资料,需要的朋友可以参考下

    rmi原理-chn-pdf

    rmi原理介绍及介绍,适合重新温习,中文版pdf

    rmi:RMI - 数据传输

    介绍 该项目允许您操作通过 RMI 分布的对象。 RMI 允许您在多个虚拟机之间共享资源(对象)。 建筑学 UML图 脚本 姓 描述 树_1.sh 模拟一个 6 节点树。 消息由节点 1(根)初始化。 树_2.sh 同上,只是消息由...

Global site tag (gtag.js) - Google Analytics