`
hz_chenwenbiao
  • 浏览: 1007733 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论
阅读更多
    RMI可以从网上找到多种的实现方式,我从网上找了两种实现方式,并测试过是可行了:
(一)

    分布式对象技术主要是在分布式异构环境下建立应用系统框架和对象构件。在应用系统框架的支撑下,开发者可以将软件功能封装为更易管理和使用的对象,这些对象可以跨越不同的软、硬件平台进行互操作。目前,分布式互操作标准主要有Microsoft的COM/DCOM标准、Sun公司的Java RMI标准和OMG组织的CORBA标准。
原文地址:
http://blog.csdn.net/javamxj/archive/2005/02/06/282659.aspx


Java RMI简介

   远程方法调用(RMI,Remote Method Invocation)是jdk1.1中引入的分布式对象软件包,它的出现大大简化了分布异构环境中Java应用之间的通信。

   要使用RMI,必须构建四个主要的类:远程对象的本地接口、远程对象实现、RMI客户机和RMI服务器。RMI服务器生成远程对象实现的一个实例,并用一个专有的URL注册。RMI客户机在远程RMI服务器上查找服务对象,并将它转换成本地接口类型,然后像对待一个本地对象一样使用它。

   下面是一个简单的RMI实例,RMI客户机通过RMI服务器提供的方法输出一个语句。例子虽然很简单,但掌握了Java RMI调用的基本原理和方法,在实现复杂应用时,我们需要做的也只是完善远程对象的实现类而已。


RMI实例分析

1.远程对象的本地接口声明(RMIOperate.java)

  • 该类仅仅是一个接口声明,RMI客户机可以直接使用它,RMI服务器必须通过一个远程对象来实现它,并用某个专有的URL注册它的一个实例。
  • 远程接口扩展 java.rmi.Remote 接口。
  • 除了所有应用程序特定的例外之外,每个方法还必须在 throws 子句中声明 java.rmi.RemoteException(或 RemoteException 的父类)。

Hello.Java
/* * @author javamxj (CSDN Blog) 创建日期 2004-12-27 */   
import java.rmi.*;    
// RMI本地接口必须从Remote接口派生    
public interface Hello extends Remote {        
  // 接口中的具体方法声明,注意必须声明抛出RemoteException        
  String sayHello(String name) throws RemoteException;    
}    
    

2.远程对象实现类

  这个类应实现RMI客户机调用的远程服务对象的本地接口,它必须从UnicastRemoteObject继承,构造函数应抛出RemoteException异常。
HelloImpl.java

/* * @author javamxj (CSDN Blog) 创建日期 2004-12-27 */   
import java.rmi.*;    
import javax.rmi.PortableRemoteObject;    
public class HelloImpl extends PortableRemoteObject implements Hello {        
  /* 构造函数 */        
  public HelloImpl() throws RemoteException {     
    super();        
  }        
  /* 实现本地接口中声明的'sayHello()'方法 */        
  public String sayHello(String message) throws RemoteException {    
    System.out.println("我在RMI的服务器端,客户端正在调用'sayHello'方法。 ");            
    System.out.println("Hello  " + message);        return message;        
  }    
}    


3.RMI服务器类

  该类创建远程对象实现类HelloImpl的一个实例,然后通过一个专有的URL来注册它。所谓注册就是通过Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,将HelloImpl实例绑定到指定的URL上。

/* * @author javamxj (CSDN Blog) 创建日期 2004-12-27 */   
import java.rmi.*;    
public class HelloServer {        
  public static void main(String[] args) {            
    // 在服务器端设置安全机制                     
    /*              
    if (System.getSecurityManager() == null) {                  
      System.setSecurityManager(new RMISecurityManager());               
    }           
    */   
    try {                
      System.out.println("开始 RMI Server ...");                
      /* 创建远程对象的实现实例 */                
      HelloImpl hImpl = new HelloImpl();                
      System.out.println("将实例注册到专有的URL ");                
      Naming.rebind("HelloService", hImpl);                            
      System.out.println("等待RMI客户端调用...");                
      System.out.println("");            
    } catch (Exception e) {                
      System.out.println("错误: " + e);            
    }        
  }    
}   


请注意有关 rebind 方法调用的下列参数:

第一个参数是 URL 格式的 java.lang.String,表示远程对象的位置和名字。 需要将 myhost 的值更改为服务器名或 IP 地址。否则,如果在 URL 中省略,则主机缺省值为当前主机,而且在 URL 中无需指定协议(例如“HelloServer”)。
在 URL 中,可以选择提供端口号:例如“//myhost:1234/HelloServer”。端口缺省值为 1099。除非服务器在缺省 1099 端口上创建注册服务程序,否则需要指定端口号。
第二个参数为从中调用远程方法的对象实现引用。
RMI 运行时将用对远程对象 stub 程序的引用代替由 hImpl 参数指定的实际远程对象引用。远程实现对象(如 HelloImpl 实例)将始终不离开创建它们的虚拟机。因此,当客户机在服务器的远程对象注册服务程序中执行查找时,将返回包含该实现的 stub 程序的对象。

4.RMI客户机类

  • RMI客户使用java.rmi.Naming.lookup()方法,在指定的远程主机上查找RMI服务对象,若找到就把它转换成本地接口RMIOperate类型。它与CORBA不同之处在于RMI客户机必须知道提供RMI服务主机的URL,这个URL可以通过rmi://host/path或rmi://host:port/path来指定,如果省略端口号,就默认使用1099。 
  • Java.rmi.Naming.lookup()方法可能产生三个异常:Java.rmi.RemoteException、Java.rmi.NotBoundException、java.net. MalformedURLException,三个异常都需要捕获。


/* * @author javamxj (CSDN Blog) 创建日期 2004-12-27 */   
import java.rmi.*;    
public class HelloClient {        
  public static void main(String[] args) {            
    //   在服务器端设置安全机制                     
    /*              
    if (System.getSecurityManager() == null) {                  
      System.setSecurityManager(new RMISecurityManager());               
    }           
    */                 
    /* 默认为本地主机和默认端口 */            
    String host = "localhost:1099";            
    /* 带输入参数时,将host设置为指定主机 */            
    if (args.length > 0)                
      host = args[0];           
    try {                
      /* 根据指定的URL定位远程实现对象 */                
      /* “h”是一个标识符,我们将用它指向实现“Hello”接口的远程对象 */                
      Hello h = (Hello) Naming.lookup("rmi://" + host + "/HelloService");                            
      System.out.println("实现“Hello”接口的远程对象: " + h);                
      System.out.println("我在客户端,开始调用RMI服务器端的'sayHello'方法");                
      System.out.println("欢迎,  " + h.sayHello("javamxj blog"));            
    } catch (Exception ex)     
    {                
      System.out.println("错误 " + ex);            
    }        
  }    
}    


5. 编译代码与运行系统:

  在MS-DOS环境下,创建一个D:\RMISample目录,把上面4个文件复制到这个目录下,然后在此目录下新建两个文件夹:client和server(把它们分别看作是客户端与服务端)。

(1).编译所有的源代码
   D:\RMISample> javac *.java

(2).生成客户端存根和服务器框架
   D:\RMISample> rmic HelloImpl
   这将生成HelloImpl_Stub.class
  ( 注:如果需要查看这个类的源代码,可以使用“ rmic -keep HelloImpl”语句)

(3).把Hello.class、HelloClient.class、HelloImpl_Stub.class复制到client目录;
   把Hello.class、HelloServer.class、HelloImpl_Stub.class 复制到server目录。

(4).启动RMI注册
   D:\RMISample\server>rmiregistry
  (注: 我是在命令控制台下运行这个系统的,必须开启三个控制台窗口,一个运行RMIRegistry,一个运行服务器,还有一个运行客户端。)

(5).运行和调用

● 在服务器上执行HelloServer
D:\RMISample\server>java HelloServer

● 在本地客户机上运行HelloClient
D:\RMISample\client>java HelloClient

● 在远程客户机上运行HelloClient(须指明RMI服务器主机名或IP地址)(也就是传参数去运行客户端代码)
  java HelloClient  222.222.34.34



  还有一点要注意,在上面的例子中我注释了安全管理的代码,如果把注释去掉,那么需要建立一个安全策略文件,比如其文件名为 policy.txt,内容如下:
grant {
permission java.security.AllPermission "", "";
};
这是一条简单的安全策略,它允许任何人做任何事,对于你的更加关键性的应用,你必须指定更加详细安全策略。把这个文件复制到Client和Server目录,然后如下运行:
D:\RMISample\server>java -Djava.security.policy=policy.txt HelloServer
D:\RMISample\client>java -Djava.security.policy=policy.txt HelloClient
来自:
(二)用MyEclipse可以实现


本实例为参考多篇文章写就而成,网上及书上各类文章介绍如何使用RMI有多种实例可参考,譬如有:
1. 用命令rmiregistry启动RMI注册服务的
2. 同时创建存根(stub)和骨架(skeleton)的
3. 只创建存根类的的(jdk1.2以后版本)
4. 通过RemoteRef和rmi://协议字串方式的
5. 比较少讲到的用LocateRegistry直接在代码上启动RMI注册服务的。
以上描述并非明显分类,比如,你总是可以选择用rmiregistry或者代码LocateRegistry启动RMI注册服务
下面我将介绍一个完整的实例,让初学者能快速体验RMI的功用。
分为以下四个步骤
1. 创建远程接口及声明远程方法(HelloInterface.java)
2. 实现远程接口及远程方法(继承UnicastRemoteObject)(Hello.java)
3. 启动RMI注册服务,并注册远程对象(HelloServer.java)
4. 客户端查找远程对象,并调用远程方法(HelloClient)
5. 执行程序:启动服务HelloServer;运行客户端HelloClient进行调用
具体代码及对应步骤如下:
1. 创建远程接口及声明远程方法(HelloInterface.java)
java 代码
import java.rmi.*;

/**
 * 远程接口必须扩展接口java.rmi.Remote
 */
public interface HelloInterface extends Remote {
	/**
	 * 远程接口方法必须抛出 java.rmi.RemoteException
	 */
	public String say() throws RemoteException;
}


2. 实现远程接口及远程方法(继承UnicastRemoteObject)Hello.java
java 代码
/**
 * 扩展了UnicastRemoteObject类,并实现远程接口 HelloInterface
 */
public class Hello extends UnicastRemoteObject implements HelloInterface {
	private String message;

	/**
	 * 必须定义构造方法,即使是默认构造方法,也必须把它明确地写出来,因为它必须抛出出RemoteException异常
	 */
	public Hello(String msg) throws RemoteException {
		message = msg;
	}

	/**
	 * 远程接口方法的实现
	 */
	public String say() throws RemoteException {
		System.out.println("Called by HelloClient");
		return message;
	}
}


3. 启动RMI注册服务,并注册远程对象(HelloServer.java)
java 代码
public class HelloServer {
	/**
	 * 启动 RMI 注册服务并进行对象注册
	 */
	public static void main(String[] argv) {
		try {
			// 启动RMI注册服务,指定端口为1099 (1099为默认端口)
			// 也可以通过命令 $java_home/bin/rmiregistry 1099启动
			// 这里用这种方式避免了再打开一个DOS窗口
			// 而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用
			LocateRegistry.createRegistry(1099);

			// 创建远程对象的一个或多个实例,下面是hello对象
			// 可以用不同名字注册不同的实例
			HelloInterface hello = new Hello("Hello, world!");

			// 把hello注册到RMI注册服务器上,命名为Hello
			Naming.rebind("Hello", hello);

			// 如果要把hello实例注册到另一台启动了RMI注册服务的机器上
			// Naming.rebind("//192.168.1.105:1099/Hello",hello);

			System.out.println("Hello Server is ready.");
		} catch (Exception e) {
			System.out.println("Hello Server failed: " + e);
		}
	}
}


4. 客户端查找远程对象,并调用远程方法(HelloClient)
java 代码
public class HelloClient    
{    
   /**   
    * 查找远程对象并调用远程方法   
    */   
   public static void main(String[] argv)    
   {    
      try   
      {    
         HelloInterface hello = (HelloInterface) Naming.lookup("Hello");    
             
         //如果要从另一台启动了RMI注册服务的机器上查找hello实例    
         //HelloInterface hello = (HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");    
             
         //调用远程方法    
         System.out.println(hello.say());    
      }    
      catch (Exception e)    
      {    
         System.out.println("HelloClient exception: " + e);    
      }    
   }    
}    


5. 执行程序:启动服务HelloServer;运行客户端HelloClient进行调用
代码如何编译这里就不细讲
(1)打开一个Dos窗口执行命令 java com.unmi.HelloServer 启动服务HelloServer
E:workspaceTestRMIbin>java com.unmi.HelloServer
Hello Server is ready.
运行成功则可以看到 Hello Server is ready
(2)打开另一个Dos窗口执行命令 java com.unmi.HelloClient 运行客户端程序
E:workspaceTestRMIbin>java com.unmi.HelloClient
Hello, world!
调用成功则可以看到 Hello, world!
并且在启动服务端的窗口中看到紧跟 Hello Server is ready. 打印出
Called by HelloClient
如果您能一路顺畅的执行到这里,恭喜!您已度过了一个轻快的RMI之旅。
最后来个说明:
本实例中并没有用到JDK所带的命令 rmic 编译实现类得到存根(Stub)类,也没用命令 rmiregistry 命令来启动RMI注册服务。在启动 rmiregistry之前必须能让它加载到相应的stub类,这就是造成**_Stub 类找不到的原因。
如果只是按上面的代码,则服务程序 HelloServer 和客户端程序 HelloClient 都必须运行在本机(如此则RMI有何意义呢?);别急,只要修改HelloClient类,使用第二种形式的lookup查找语句,注释第一条 lookup语句,取消注释第二条lookup语句
         //HelloInterface hello = (HelloInterface) Naming.lookup("Hello");
       
         //如果要从另一台启动了RMI注册服务的机器上查找hello实例
         HelloInterface hello = (HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");
其中的IP地址和端口号1099为 RMI 注册服务器的IP和端口号,这样你的HelloClient就可以在另一台机器运行了,当然HelloInterface类必须能找到(但也可指定参数- Djava.rmi.server.codebase从网络加载HelloInterface类)。lookup("Hello")默认为从本机 127.0.0.1的1099端口上查找Hello命令对象,如果第二条语句写成lookup("192.168.1.105/Hello")与原语句是同等的,因为默认端口号就是1099。
代码中 HelloServer 和 HelloClient 省略了设置安全管理器的过程 System.setSecurityManager(new RMISecurityManager()); ,如果设置的安全管理则必须编写相应的访问策略文件,并且在执行时指定参数
无论是启动服务端还是客户端都可以用参数 -Djava.rmi.server.codebase=http://unmi.blogcn.cn/bin 的形式,像JNP一样从网络上加载类,这样更方便于RMI客户端的部署,如RMI客户端是一个Applet
可以拿单独一台机器运行 rmiregistry (它需要能加载到相应的stub类,设置classpath)或用LocateRegistry.createRegistry(port),只作为 RMI远程对象的RMI集中注册的服务器,真正提供服务对象只往上注册,客户端只需从注册服务器上查找远程对象引用,然后调用远程方法,具体由谁提供服务由注册服务器来帮助联络。
还可以用 RMI Activation 编程方式来实现RMI远程方法调用,具体请参考 http://java.sun.com/j2se/1.4.2/docs/guide/rmi/activation.html
把HelloServer和HelloClient中的 "//192.168.1.105:1099/Hello 写成 rmi:/192.168.1.105:1099/Hello 感觉会好看一些,因为直接感觉就是在处理rmi协议。

    当我们要在client端用server的服务时,我们可以将server的接口打包,具体做法是右键选择Export->java->jar file再展开项目,只将接口类打钩,然后导出,在client端再导入,就可以用了,这里注意的是我们只打包接口,不能打包实现类,不然人家可以反编译就得到你的原文件,而且这也不是分布式的模式
来自:
http://qiuhanstar.blog.163.com/blog/static/3085469520102411351327/
分享到:
评论

相关推荐

    rmi学习资料

    在提供的学习资料中,"rmi入门教程,简单明了(转).htm"和"RMI基础教程 - 深海有约 - BlogJava.htm"很可能是两篇关于RMI基础知识的教程,它们可能涵盖了RMI的基本概念、设置步骤、示例代码以及常见问题。...

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

    ### RMI基础知识与实践 #### 一、Java RMI简介 Java Remote Method Invocation (RMI) 是Java平台提供的一种分布式计算技术,允许开发者在不同Java虚拟机(JVM)之间调用远程对象的方法,从而实现分布式应用程序的...

    一个简单的RMI例子Java源代码,用于学习理解RMI

    学习这个简单的RMI示例,可以帮助你了解如何在Java中设置和使用RMI,包括创建远程接口,实现远程对象,注册到RMI注册表,以及在客户端进行远程方法调用。这将为你构建更复杂的分布式系统打下基础。

    rmi学习

    在这个“rmi学习”资料中,我们可以深入探讨RMI的基础知识、工作原理以及如何通过实例来学习和应用RMI。 一、RMI基础知识 1. RMI架构:RMI系统由三部分组成——远程接口、远程对象和RMI注册表。远程接口定义了远程...

    (转)通用JAVA RMI服务器框架

    【标题】:“(转)通用JAVA RMI服务器框架” 【正文】: 在Java远程方法调用(Remote Method Invocation,RMI)技术中,构建一个通用的服务器框架是提高开发效率和代码可复用性的关键。Java RMI允许分布式计算,使得...

    RMI-IIOP 基于SUN

    学习和掌握RMI-IIOP技术,不仅可以提升开发者的分布式编程技能,也有助于设计和实现更高效、更健壮的企业级应用。通过实践和研究提供的资源,初学者可以逐步了解和掌握这一强大的分布式计算工具。

    数学方法论RMI方法学习教案.pptx

    《数学方法论RMI方法学习教案》探讨了数学中一种重要的问题解决策略——关系映射反演(Relational Mapping Inversion,简称RMI)方法。RMI方法是数学方法论中的核心概念,它强调通过将复杂问题转化为同构的简单问题...

    RMI学习例子

    在这个“RMI学习例子”中,我们有两个关键部分:服务端和客户端,它们都是使用Java 1.5编写的,因此不需要通过`rmic`命令来手动生成存根(stub)和 skeletons 文件。 首先,让我们深入理解RMI的工作原理。RMI的核心...

    java RMI技术实现的网络聊天室

    Java RMI(Remote Method Invocation)技术是Java平台中用于分布式计算的一种机制,它允许一个Java对象调用远程...通过这个项目,开发者可以学习到如何使用RMI创建分布式应用,以及如何处理并发和网络通信等问题。

    RMI教程-入门经典

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许Java对象在不同的Java虚拟机之间进行通信,仿佛这些对象都...通过不断学习和实践,开发者可以充分利用RMI的强大功能。

    (转)用c++实现java的rmi服务

    在IT行业中,远程方法调用...开发者可以通过研究源码,学习如何在没有Java RMI框架的情况下,利用C++的灵活性和强大功能构建自己的分布式系统。同时,这也是一种跨语言通信的实践,对于提升跨平台开发能力大有裨益。

    Java RMI demo多对象

    Java Remote Method Invocation(RMI)是Java平台上的一个特性,它允许在分布式环境中进行对象间的交互,即在一台机器上的对象可以...通过学习和实践,开发者可以有效地利用RMI的优势来设计和实现复杂的分布式系统。

    java rmi HelloWorld版(源码)

    这个"java rmi HelloWorld版(源码)"的压缩包文件提供了一个简单的RMI应用示例,帮助开发者了解和学习RMI的基本原理和使用。 RMI的核心概念包括: 1. **远程接口(Remote Interface)**:这是定义远程方法的接口...

    RMI基础代码小程序

    Java RMI(Remote Method Invocation,...学习这个RMI基础代码小程序,可以帮助理解RMI的基本工作原理,为进一步探索Java的分布式计算打下基础。此外,理解并掌握RMI有助于开发跨JVM的应用,例如分布式系统、云服务等。

    java RMI demo

    通过"java RMI demo"的学习,开发者可以掌握如何创建、注册远程对象,以及如何在客户端进行调用。理解RMI的工作原理和配置,对于开发分布式Java应用至关重要。同时,这也涉及到了网络编程、多线程和异常处理等相关...

    synaptics s3202 寄存器手册以及RMI4手册

    接着,他们会依据RMI4接口指南,学习如何与S3202进行通信,配置传输协议,实现触摸事件的正确识别和处理。此外,手册还会涵盖故障排查和性能优化的技巧,帮助开发者解决在实际应用中可能遇到的问题。 S3202寄存器...

    java_rmi.zip

    Java RMI(Remote Method Invocation,远程...使用这个“java_rmi.zip”中的资源,你可以学习如何设置RMI环境,编写远程接口和实现,以及创建和调用远程对象。同时,了解相关的最佳实践和安全注意事项也是十分重要的。

    RMI demo

    【RMI(远程方法调用)技术详解】 ...在实际开发中,可以通过阅读"RMI 初步研究报告.doc"文档,深入了解RMI的具体细节和最佳实践,以及在"client_src"和"server_src"目录下的源代码示例,进一步学习和掌握RMI的应用。

    RMI实现的网络五子棋

    总之,"RMI实现的网络五子棋"项目是一个融合了Java分布式计算技术、面向对象设计和系统建模的实践案例,对于学习Java RMI、UML建模以及多人在线游戏开发的程序员来说,这是一个有价值的参考和学习资源。它不仅展示了...

    HTTP客户端,HTTP服务器,RMI客户端和服务器

    在实验中,你可能会学习到如何创建RMI服务接口,实现该接口的服务器端,以及在客户端如何查找和调用远程服务。 具体到实验文件"rmi",这可能是RMI相关代码或者教程的集合,可能包含了服务器端和客户端的示例代码,...

Global site tag (gtag.js) - Google Analytics