`

RMI简介

阅读更多

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简介及实例

    java RMI开发指南,详细地讲述了java RMI的原理,有具体的实例描述。

    bea RMI 培训

    分布式对象 RMI简介 RMI体系结构 RMI服务端程序开发 RMI客户端程序开发 RMI应用程序的部署 RMI的最佳实践

    J2EE应用开发详解

    208 11.7.1 基于容器管理事务 209 11.7.2 基于Bean管理的事务 210 11.8 EJB拦截器 212 11.9 EJB定时服务 214 11.10 EJB安全管理 214 11.11 小结 216 第12章 RMI 217 12.1 RMI简介 217 12.1.1 RMI的架构 218 12.1.2 ...

    Java中简单的分布式调用RMI

    前言  我们先来看一个例子:  系统中目前存在两个 JAVA 服务,分别是服务A、服务B。现在服务A 想要调用服务B中的某个服务,我们怎么实现呢?  有人觉得这不很简单,服务B暴露一个服务接口,...  RMI 简介  RMI

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

    安装$ mvn install$ java -Djava.security.policy=RMI-Server/server.policy -jar RMI-Server/target/RMI-Server-1.0.jar$ java -Djava.security.policy=RMI-Client/client.policy -jar RMI-Client/target/RMI-...

    BrokerTool_java.rar_brokerto_java源代码 RMI_portfolio_rmi

    简介:使用RMI编程,服务端和客户端的BrokerTool。 完整实现所有功能,包括stock 和 portfolio。 MVC范式,RMI带回调,客户端同步刷新。 内容:src文件夹 -- 所有源代码 server.bat -- 服务端 client.bat -- ...

    RMI原理及实现(JAVA)

    RMI原理及实现 简介  RMI是远程方法调用的简称,象其名称暗示的那样,它能够帮助我们查找并执行远程对象的方法。通俗地说,远程调用就象将一个class放在A机器上,然后在B机器中调用这个class的方法。

    Dubbo简介.docx

    rmi : 采用 JDK 标准的 rmi 协议实现,传输参数和返回参数对象需要实现 Serializable 接口,使用 java 标准序列化机制,使用阻塞式短连接,传输数 据包大小混合,消费者和提供者个数差不多,可传文件,传输协议 ...

    XML简介+SOAP+XML-RPC

    介绍了XML的basics,parsing以及RMI等

    Activiti6.0工作流引擎springboot项目代码

    (Activiti6.0集成springboot工作流引擎模板代码)Activiti6.0工作流引擎介绍与总结,工作流简介、流程体验、 Activiti与spring集成

    清华大学JAVA教程

    ◇9.3 RMI的基本概念和编程简介 ◇9.4 EJB简介 ◇本讲小结 ◇课后习题 ★ 第十讲 JSP与Servlet ◇课前索引 ◇10.1 Servlet的概念、配置与运行 ◇10.2 Servlet的应用实例 ◇10.3 JSP简介 ◇10.4 JSP和...

    JAVA 清华大学 教程

    ★ 第一讲 Java语言概述 ◇课前索引 ◇1.1 java语言的发展史 ◇1.2 java的工作原理 ◇1.3 一切都是对象 ...◇9.3 RMI的基本概念和编程简介 ◇9.4 EJB简介 ◇本讲小结 ◇课后习题 ★ 第十讲 JSP与Servlet

    Java编程语言详细教程

    ◇9.3 RMI的基本概念和编程简介 ◇9.4 EJB简介 ◇本讲小结 ◇课后习题 ★ 第十讲 JSP与Servlet ◇课前索引 ◇10.1 Servlet的概念、配置与运行 ◇10.2 Servlet的应用实例 ◇10.3 JSP简介 ◇10.4 JSP和...

    JAVA清华大学教程

    清华大学java课程学习使用教程 ★ 第一讲 Java语言概述 ◇课前索引 ◇1.1 java语言的发展史 ...◇9.3 RMI的基本概念和编程简介 ◇9.4 EJB简介 ◇本讲小结 ◇课后习题 ★ 第十讲 JSP与Servlet

    JSP高级编程          

    4.2 远程方法调用RMI 技术 4.3 CORBA 技术 4.4 JNDI 技术 4.5 本章小结6 第二部分 JSP 技术和XML 技术 第5 章 XML 简介 5.1 XML 简介及其语法规则 5.2 DTD 的书写及实例 目录 5.3 CSS 与XSL 及其实例 5.4 XHTML 简介...

    JSP高级编程(全)

    4.2 远程方法调用RMI 技术 4.3 CORBA 技术 4.4 JNDI 技术 4.5 本章小结6 第二部分 JSP 技术和XML 技术 第5 章 XML 简介 5.1 XML 简介及其语法规则 5.2 DTD 的书写及实例 5.3 CSS 与XSL 及其实例 5.4 XHTML 简介 5.5 ...

    j2ee基础知识

    J2EE简介及学习方法 J2EE基础技术  XML、RMI、JNDI 、JMS

    J2EE的13种核心技术简介

    支撑J2EE的13种核心技术:JDBC, JNDI, EJBs, RMI, JSP, Java servlets, XML, JMS, Java IDL, JTS, JTA, JavaMail 和 JAF.

    J2EE的13种核心技术简介.doc

    在本文中将解释支撑J2EE的13种核心技术:JDBC,JNDI,EJBs,RMI,JSP,Javaservlets,XML,JMS,JavaIDL, JTS,JTA,JavaMail和JAF,同时还将描述在何时、何处需要使用这些技术。当然,我还要介绍这些不同的技术之间是如何交互...

Global site tag (gtag.js) - Google Analytics