﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-漫步红林-文章分类-RMI</title><link>http://www.blogjava.net/hyint/category/37822.html</link><description>品味技术与生活之间的差距，追求代码与国画之间的艺术.</description><language>zh-cn</language><lastBuildDate>Sat, 28 Feb 2009 16:18:55 GMT</lastBuildDate><pubDate>Sat, 28 Feb 2009 16:18:55 GMT</pubDate><ttl>60</ttl><item><title>Start RMI in one ---- Thinking</title><link>http://www.blogjava.net/hyint/articles/257068.html</link><dc:creator>苦瓜</dc:creator><author>苦瓜</author><pubDate>Fri, 27 Feb 2009 09:10:00 GMT</pubDate><guid>http://www.blogjava.net/hyint/articles/257068.html</guid><wfw:comment>http://www.blogjava.net/hyint/comments/257068.html</wfw:comment><comments>http://www.blogjava.net/hyint/articles/257068.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hyint/comments/commentRss/257068.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hyint/services/trackbacks/257068.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;什么是 RMI？<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当你在JDK的帮助文档中输入Remote,或者你也可以浏览 java.rmi包中的所有class，你也许不知道它是做什么的！首先定义一下：<br />
RMI ------Remote&nbsp;&nbsp; Method&nbsp; Invocation (远程方法调用)。是用Java在JDK1.1中实现的，它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言，其巨大的威力就体现在它强大的开发分布式网络应用的能力上，而RMI就是开发百分之百纯 Java 的网络分布式应用系统的核心解决方案之一。其实它可以被看作是 RPC 的 Java 版本。但是传统 RPC 并不能很好地应用于分布式对象系统。而 Java&nbsp;&nbsp; RMI&nbsp; 则支持存储于不同地址空间的程序级对象之间彼此进行通信，实现远程对象之间的无缝远程调用。RMI 目前使用Java远程消息交换协议 JRMP（Java&nbsp; Remote&nbsp; Messaging&nbsp; Protocol）进行通信。JRMP 是专为 Java 的远程对象制定的协议。因此，Java&nbsp; RMI 具有 Java 的 "Write&nbsp; Once, Run&nbsp; Anywhere" 的优点，是分布式应用系统的百分之百纯Java解决方案。用Java&nbsp;RMI开发的应用系统可以部署在任何支持 JRE（Java&nbsp;Run&nbsp;Environment&nbsp;Java，运行环境）的平台上。但由于JRMP是专为Java对象制定的，因此，RMI 对于用非 Java 语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。本文拟从程序的角度举例介绍怎样利用RMI实现Java分布式应用，在现在的分布式中，大多数都是采用WebService，因为传输数据基于 XML，所以可以达到平台无关，语言无关的优点。<br />
<br />
<span style="font-size: 24pt"><span style="font-size: 18pt">1、RMI的运行机制</span><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RMI应用程序通常包括两个独立的程序：服务器程序 和 客户机程序。典型的服务器应用程序将创建多个远程对象，使这些远程对象能够被引用，然后等待客户机调用这些远程对象的方法。而典型的客户机程序则从服务器中得到一个或多个远程对象的引用，然后调用远程对象的方法。RMI为服务器和客户机进行通信和信息传递提供了一种机制。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在与远程对象的通信过程中，RMI使用标准机制：stub 和 skeleton。远程对象的 stub 担当远程对象的客户本地代表或代理人角色。调用程序将调用本地stub的方法，而本地stub将负责执行对远程对象的方法调用。在RMI中，远程对象的stub与该远程对象所实现的远程接口集相同。调用stub的方法时将执行下列操作：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;(1)&nbsp;初始化与包含远程对象的远程虚拟机的连接；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;对远程虚拟机的参数进行编组（写入并传输）；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;等待方法调用结果；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)&nbsp;解编（读取）返回值或返回的异常；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)&nbsp;将值返回给调用程序。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了向调用程序展示比较简单的调用机制，stub将参数的序列化和网络级通信等细节隐藏了起来。在远程虚拟机中，每个远程对象都可以有相应的skeleton（在JDK1.2环境中无需使用skeleton）。Skeleton负责将调用分配给实际的远程对象实现。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它在接收方法调用时执行下列操作：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)&nbsp;解编（读取）远程方法的参数；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;调用实际远程对象实现上的方法；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;将结果（返回值或异常）编组（写入并传输）给调用程序。stub和skeleton由rmic编译器生成。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;利用RMI编写分布式对象应用程序需要完成以下工作：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)&nbsp;&nbsp;&nbsp; 定位远程对象。应用程序可使用两种机制中的一种得到对远程对象的引用。它既可用RMI的简单命名工具rmiregistry来注册它的远程对<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;象，也可以将远程对象引用作为常规操作的一部分来进行传递和返回。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)&nbsp;&nbsp;&nbsp; 与远程对象通信。远程对象间通信的细节由RMI处理，对于程序员来说，远程通信看起来就像标准的Java方法调用。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)&nbsp;&nbsp;&nbsp;&nbsp; 给作为参数或返回值传递的对象加载类字节码。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因为RMI允许调用程序将纯Java对象传给远程对象，所以，RMI将提供必要的机制，既可以加载对象的代码又可以传输对象的数据。在RMI分布式应用程序运行时，服务器调用注册服务程序以使名字与远程对象相关联。客户机在服务器上的注册服务程序中用远程对象的名字查找该远程对象，然后调用它的方法。 <br />
<br />
<span style="font-size: 18pt">2、对象序列化 </span><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在 RMI 分布式应用系统中，服务器与客户机之间传递的 Java 对象必须是可序列化的对象。不可序列化的对象不能在对象流中进行传递。对象序列化扩展了核心Java输入/输出类，同时也支持对象。对象序列化支持把对象编码以及将通过它们可访问到的对象编码变成字节流；同时，它也支持流中对象图形的互补重构造。序列化用于轻型持久性和借助于套接字或远程方法调用 ( RMI ) 进行的通信。序列化中现在包括一个&nbsp;API(Application&nbsp;Programming&nbsp;Interface，应用程序接口)，允许独立于类的域指定对象的序列化数据，并允许使用现有协议将序列化数据域写入流中或从流中读取，以确保与缺省读写机制的兼容性。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为编写应用程序，除多数瞬态应用程序外，都必须具备存储和检索&nbsp;Java对象的能力。以序列化方式存储和检索对象的关键在于提供重新构造该对象所需的足够对象状态。存储到流的对象可能会支持&nbsp;Serializable（可序列化）或&nbsp;Externalizable（可外部化）接口。对于Java对象，序列化形式必须能标识和校验存储其内容的对象所属的&nbsp;Java类，并且将该内容还原为新的实例。对于可序列化对象，流将提供足够的信息将流的域还原为类的兼容版本。对于可外部化对象，类将全权负责其内容的外部格式。序列化&nbsp;Java&nbsp;对象的目的是：提供一种简单但可扩充的机制，以序列化方式维护&nbsp;Java对象的类型及安全属性；具有支持编组和解编的扩展能力以满足远程对象的需要；具有可扩展性以支持&nbsp;Java&nbsp;对象的简单持久性；只有在自定义时，才需对每个类提供序列化自实现；允许对象定义其外部格式。 <br />
<br />
<span style="font-size: 18pt">3、分布式应用的实现和运行步骤 </span><br />
<br />
编写Java&nbsp;RMI分布式应用程序的步骤主要包括以下几步： <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)&nbsp;&nbsp; 将远程类的功能定义为Java接口。在Java中，远程对象是实现远程接口的类的实例。在远程接口中声明每个要远程调用的方法。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 远程接口具有如下特点：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)&nbsp;&nbsp; 远程接口必须声明为public。如果不这样，则除非客户端与远程接口在同一个包内，否则当试图装入实现该远程接口的远程对<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 象时会得到错误结果。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)&nbsp;&nbsp; 远程对象扩展java.rmi.Remote接口。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)&nbsp; &nbsp;除了所有应用程序特定的例外之外，每个方法还必须抛出java.rmi.RemoteException例外。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;4)&nbsp;&nbsp; 任何作为参数或返回值传送的远程对象的数据类型必须声明为远程接口类型，而不是实现类。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2)&nbsp;&nbsp; 编写和实现服务器类。该类是实现(1)中定义的远程接口。所以在该类中至少要声明实现一个远程接口，并且必须具有构造方法。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在该类中还要实现远程接口中所声明的各个远程方法。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3)&nbsp;&nbsp;&nbsp; 编写使用远程服务的客户机程序。在该类中使用java.rmi.Naming中的lookup()方法获得对远程对象的引用，依据需要调用该引用的远程方<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;法，其调用方式和对本地对象方法的调用相同。 <br />
<br />
实现了服务器和客户机的程序后，就是编译和运行该RMI系统。其步骤有：&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;(1)&nbsp;&nbsp;&nbsp;使用javac编译远程接口类，远程接口实现类和客户机程序。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;(2)&nbsp;&nbsp; 使用rmic编译器生成实现类的stub和skeleton。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;(3)&nbsp;&nbsp; 启动RMI注册服务程序rmiregistry。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;(4)&nbsp; &nbsp;启动服务器端程序。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;(5)&nbsp;&nbsp; 启动客户机程序。&nbsp;<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在当前RMI / IIOP 的使用中，RMI并没有被广泛使用，而是被封装成多种形式，譬如WebService，EJB等都继承了 RMI 的分布式思想，而RMI的缺点确实不得不让大家为了这效率而捏把汗，因为对象传输过程是串行化的，所以效率奇低。<br />
<img src ="http://www.blogjava.net/hyint/aggbug/257068.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hyint/" target="_blank">苦瓜</a> 2009-02-27 17:10 <a href="http://www.blogjava.net/hyint/articles/257068.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>