前几天在阿里内推一面的时候,面试官问到了一个关于java中RMI(Remote Method Invocation)的问题,当时感觉自己回答的还比较好,他比较满意,但那是因为他问的比较浅,所以自己看了一些关于java方面的书籍及网上相关资料,根据自己的理解,谈谈java中的RMI。

java中的RMI包括两种情况,一种是采用反射机制,另一种是采用实现Remote接口的方式,下面一一介绍。

一采用反射机制:

关于此种方式不过多讲述,请参看孙卫琴老师的java网络编程P242中10.2小节在远程方法调用中运用反射机制

二实现Remote接口:

先了解一些最基本的概念:

1远程对象:驻留在远程服务器上的对象是客户端要请求的对象,称作远程对象,即客户端请求远程对象调用相应的方法完成一定的业务逻辑,然后远程对象调用该方法将结果返回给客户端。

2代理与存根(Stub)

RMI不希望客户端直接与远程对象打交道,而是代之以让客户端与远程对象的代理打交道。代理的特点是:它与远程对象实现了相同的接口,也就是说它与远程对象向客户端公开了相同的方法,当客户端请求代理调用这个方法时,如果代理确认远程对象能够能够调用相同的方法,就会把实际的方法调用委派给远程对象。这种情况非常类似国家领导人与驻外国大使的关系,如果中国的某个官员要联系美国总统,需要先和驻中国的美国大使联系,然后通过他和美国总统联系,这个大使就相当于总统的远程代理对象。

RMI会帮助生成一个存根(Stub),一种特殊的字节码,让这个存根产生的对象作为远程对象的代理,代理需要驻留在客户端,即客户端需要把RMI生成的存根(Stub)复制或下载到客户端。

3Remote接口

RMI为了标识一个对象是远程对象,即为了标识该对象能够被客户端请求,需要远程对象必须实现java.rmi包中的Remote接口,也就是说只有实现了该接口的类的实例才被RMI认为是一个远程对象。Remote接口中没任何方法,仅仅起一个标识作用,因此必须扩展该接口,用来规定远程对象哪些方法是客户可以请求的。

原理示意图如下:

具体实现步骤如下:

1扩展Remote接口:定义一个接口是java.rmi包中Remote的子接口,在该接口中定义一个方法用来规定远程对象哪些方法是客户可以请求的。代码如下

package rmi;

import java.rmi.Remote;

public interface  RemoteSubject extends Remote {

	public void setHeigh(double height);
public void setWidth(double width);
public double getArea(); }

2创建远程对象:远程对象需要实现上述扩展的Remote接口,另外,RMI为了让一个对象成为远程对象还需要做一些初始化工作,该工作java中的UnicastRemoteObject已经帮我们做好了,我们只需要继承它既可。即远程对象需要实现上述扩展的Remote接口同时继承UnicastRemoteObject类(位于java.rmi.server包中)

package rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject; public class RemoteConcreteSubject extends UnicastRemoteObject implements RemoteSubject { private double width,height;
protected RemoteConcreteSubject() throws RemoteException {
super();
// TODO Auto-generated constructor stub
} @Override
public void setHeigh(double height) {
// TODO Auto-generated method stub
this.height=height;
} @Override
public void setWidth(double width) {
// TODO Auto-generated method stub
this.width=width;
} public double getArea()
{ return width*height;
}
}

3产生存根(即代理):我们使用rmic命令 远程对象类名.java文件,则会自动产生一个存根字节码文件,注意存根是在服务器端产生的,通常提供一个web服务让客户端下载该存根

4启动注册:rmiregistry:在启动远程服务器创建远程对象之前,RMI要求远程服务器必须首先启动注册rmiregistry,启动之后服务器才可以创建远程对象,然后将该远程对象注册到rmiregistry所管理的注册表中。在远程终端执行rmiregistry命令即可启动注册。

5启动远程对象服务:即服务器端运行的业务逻辑代码,远程服务通过使用java.rmi包中的Naming类调用rebind(String name,Remote obj)方法绑定一个远程对象到rmiregistry:所管理的注册表中,该方法的name参数是URL格式,obj是远程对象,将来客户端的代理将通过name找到远程对象obj.。

package rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException; public class BindRemoteObjectServer { public static void main(String[] args) {
// TODO Auto-generated method stub try {
RemoteConcreteSubject remoteObject=new RemoteConcreteSubject();
Naming.rebind("rmi://127.0.0.1/rect",remoteObject);
System.out.println("ready for client....");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }

6运行客户端程序:远程服务器端启动远程服务之后,客户端就可以运行相关程序,访问和使用远程对象。客户端使用java.rmi包中的Naming类的lookup(String name)返回一个远程对象的代理,即使用存根产生一个和远程对象具备相同接口的对象,lookup(String nane)方法中的name参数的值必须是远程对象注册的name,如:“rmi://127.0.0.1/rect”

客户端可以像使用远程对象一样来使用lookup(String nane)方法返回的远程对象的代理,这就类似上述反射机制中通过反射得到服务器端的类之后就可以调用其中个的一些方法。

package rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException; public class ClientApplication { public static void main(String[] args) {
// TODO Auto-generated method stub try {
Remote remoteObject=Naming.lookup("rmi://127.0.0.1/rect");
RemoteSubject remoteSubject=(RemoteSubject)remoteObject;
remoteSubject .setWidth(127);
remoteSubject.setHeigh(520);
double area=remoteSubject.getArea();
System.out.println(area);
} catch (MalformedURLException | RemoteException | NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }





javaRMI详解的更多相关文章

  1. jdk目录详解及其使用方法

    jdk目录详解 jdk目录详解 JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和应用程序的程序开发环境.它由一个处于操作系统层之上的 ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. AQS

    AQS介绍 AQS,即AbstractQueuedSynchronizer, 队列同步器,它是Java并发用来构建锁和其他同步组件的基础框架. AQS的核心思想是基于volatile int stat ...

  2. Linux mint界面过小无法安装(解决方法)

    安装Linux mint时,到了分区的时候,有时候会出现界面过小(就是你点击不到确定键). 如下图所示: 大家可以看到下面的确定键无法显示,导致无法安装.网上查了一下都是清一色的下载vwware to ...

  3. 记一次sql优化——left join不走索引问题

    sql一执行就卡住,然后就...杀进程了 看了一下表的大小 第一反应就是加索引,然后explain看了一下走什么索引了,结果很尴尬,三个表,只走了一个索引...一群人在那纠结为毛走不了索引. 无意间发 ...

  4. 修改hosts不必重启 立刻生效

    打开命令提示符窗口执行以下命令: 显示DNS缓存内容 ipconfig /displaydns 删除DNS缓存内容 ipconfig /flushdns ps.电脑卡的话,先关机再开机(别直接重启)

  5. ubuntu14.04 安装PIL库出现OError: decoder jpeg not available 的解决方案

    出现 OError: decoder jpeg not available 的原因是,没有装JPEG的库,同时要支持png图片的话还要装 ZLIB.FREETYPE2.LITTLECMS的库文件. 先 ...

  6. Codeforces Round #417 (Div. 2)-A. Sagheer and Crossroad

    [题意概述] 在一个十字路口 ,给定红绿灯的情况, 按逆时针方向一次给出各个路口的左转,直行,右转,以及行人车道,判断汽车是否有可能撞到行人 [题目分析] 需要在逻辑上清晰,只需要把所有情况列出来即可 ...

  7. OpenCV+VS2013 属性表配置

    简介 计算机视觉任务越来越多的依赖著名的开源计算机视觉库OpenCV.OpenCV 2.0 包含了一系列精心设计数据结构和经过优化的视觉算法,大家可以短时间内开发一个不错的视觉应用.OpenCV支持多 ...

  8. 准备在CSDN知识库建立一个Ext JS的知识库

    CSDN近期正在建立一个知识库,目标是打造身边的技术百科全书 ,我觉得这创意挺好,就像stackoverflow一样,常见的问题在里面基本都有了,只要通过搜索就能找到所需的答案. 现在,大家对于Ext ...

  9. mongo 写分析

    写操作 复制集 mongo所有的节点都是写入到primary节点,同时写入oplog,secondary 节点会持续的从primary节点上复制oplog的信息,然后根据oplog写数据.second ...

  10. 【mybatis深度历险系列】mybatis中的输入映射和输出映射

    在前面的博文中,小编介绍了mybatis的框架原理以及入门程序,还有mybatis中开发到的两种方法,原始开发dao的方法和mapper代理方法,今天博文,我们来继续学习mybatis中的相关知识,随 ...