专栏首页ccf19881030的博客Java RMI-远程方法调用

Java RMI-远程方法调用

    最近在看《Head First设计模式》一书的代理模式时,提到了Java RMI,即Java远程方法调用这个概念。于是上网找了一些关于Java RMI的资料加以学习。

一、Java RMI概观

  RMI英文全称为:Remote Method Invocation,中文意思为:远程方法调用。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。

     RMI提供了客户辅助对象和服务辅助对象,为客户辅助对象创建和服务对象相同的方法。RMI的好处在于你不必亲自写如何网络代码和I/O代码。客户程序远程调用(即真正的服务所在)就和运行客户自己的本地机JVM上对对象进行正常方法调用一样。

    RMI将客户辅助对象成为stub(桩),服务辅助对象成为skeleton(骨架)。

    RMI结构图如下:

二、Java中如何利用RMI进行远程方法调用呢?

步骤如下:

1、制作远程接口

2、制作远程的实现

3、利用rmic产生stub和skeleton

4、启动RMI registry(rmiregistry)

5、开始远程服务

三、例子程序

MyRemote.java

/**
 * 服务器端   远程接口
 */

package RMIDemo;

/*
 * RemoteException和远程接口在java.rmi包中
 * */
import java.rmi.*;

/*
 * 定义一个远程接口,它必须扩展自java.rmi.Remote接口。
 * */
public interface MyRemote extends Remote {
	/**
	 * 所有的远程方法都必须抛出RemoteException异常。
	 * @return
	 * @throws RemoteException
	 */
	public String sayHello() throws RemoteException;
}

MyRemoteImpl.java

/**
 * 远程服务(实现)
 */
package RMIDemo;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * 
 * @author ccf
 *
 */

/**
 * 要想创建一个远程对象,扩展UnicastRemoteObject是最容易的方法。
 * 其中,MyRemote接口是你必须实现的远程接口
 */
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
	/**
	 * 你必须实现远程接口。当然你必须实现所有的接口方法,但请注意:可以不需要声明RemoteException。
	 */
	@Override
	public String sayHello() throws RemoteException {
		// TODO Auto-generated method stub
		return "Server says: 'Hey' ";
	}
	/**
	 * 你的超类(UnicastRemoteObject)构造器声明了异常,所以你必须写一个构造器,
	 * 因为这意味着你的构造器正在调用不安全的代码(它的超构造器)。
	 * @throws RemoteException
	 */
	public MyRemoteImpl() throws RemoteException{}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try{
			/**
			 * 先产生远程对象,再使用Naming.rebind()绑定到rmiregistry。
			 * 客户将使用你所注册的名称在RMI Registry中寻找它。
			 */
			MyRemote service = new MyRemoteImpl();
			Naming.rebind("RemoteHello", service);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}

}

MyRemoteClient.java

package RMIDemo;

/**
 * 用来做rmiregister lookup的Naming类在java.rmi包中。
 * 客户端测试,在客户端调用远程对象的远程方法,并返回结果。
 */
import java.rmi.*;

public class MyRemoteClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
	}
	public void go(){
		try{
			/*
			 * 返回值是Object类型,所以别忘记转换类型。
			 * 其次,在lookup函数中你需要IP地址或主机名,还有服务器被绑定/重绑定时用的名称。
			 */
			MyRemote service = (MyRemote)Naming.lookup("rmi://127.0.0.1/RemoteHello");
			
			String s = service.sayHello();
			
			System.out.println(s);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
}

博客园博主ninahan的博客Java RMI之HelloWorld篇的例子和我从《Head First设计模式》中的摘抄的例子差不多,他讲解得比较清晰!

总结:

RMI对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。这也是RMI的局限性之一。

这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。

RMI的局限性之二是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现。

四、 参考资料:

1、《Head First设计模式》第440-450页。

 2、Java RMI 服务器框架:使用异步进程管理器来包含 RMI 服务器应用程序

3、Java RMI之HelloWorld篇:Java RMI之HelloWorld篇

 4、JAVA RMI线程模型及内部实现机制 :JAVA RMI线程模型及内部实现机制

 5、JDK_API_1_6_zh_CN.CHM参考手册

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Win7下unetbootin-windows-585工具制作Ubuntu12.04 U盘启动盘

    等待至如上图所示的进度时,点击【现在重启】按钮,重启电脑,记住不要移除U盘,事先将BIOS设置为USB启动。

    ccf19881030
  • QT5.0.1在Windows下 出现QApplication: No such file or directory 问题的解决办法

          最近在Windows7下安装了最新的Qt5.0.1的Windows安装包,可以到QT官网http://qt-project.org/download...

    ccf19881030
  • PHP上传文件超过文件最大限制导致无法上传成功

         最近在学习《HeadFirst PHP & MySQL》一书的第5章“使用存储在文件中的数据”,做一个文件上传的应用时,出现了错误,就是文件无法成功上...

    ccf19881030
  • 一天一个注解-@PostConstruct简介API使用说明

    JavaEdge
  • C#:昨天,今天和明天:和 Anders Hejlsberg 座谈,第三部分

    Osborn:关于增加的匿名方法有什么特点吗?我记得当匿名方法刚被人介绍出来的时候,我和其作者聊过,他说你不得不在语言中支持这样的功能,但是为什么要这么做,却说...

    田春峰-JCJC错别字检测
  • python_类属性和实例属性

    到这里就可以完满解释上面的问题: 1. Python中属性的获取是按照从下到上的顺序来查找属性; 2. Python中的类和实例是两个完全独立的对象; 3. P...

    py3study
  • 数学救命:决斗中的概率问题!

    大数据文摘
  • 基于 HTML5 Canvas 绘制的电信网络拓扑图

    HT_hightopo
  • python序列操作

        可以通过分片操作来访问一定范围内的元素,分片由2个冒号隔开的索引来实现。左边必须大于右边,并且不包含右边。可以通过第三个数值,来指定步进。

    py3study
  • 实习经验分享|小米-产品岗

    入职一个月了,mentor很nice,愿意接受一个0基础的我还带我成长,留下了感动人心的泪水。进入状态的速度很快,入职第一天就开始做工作,但是因为一片空白,什么...

    牛客网

扫码关注云+社区

领取腾讯云代金券