转自:http://blog.csdn.net/guyuealian/article/details/51992182

一、Java RMI机制: 
       远程方法调用RMI(Remote Method Invocation),是允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。 这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中。
       Java RMI:Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能简化远程接口对象的使用。
       而RPC是远程过程调用(Remote Procedure Call)可以用于一个进程调用另一个进程(很可能在另一个远程主机上)中的过程,从而提供了过程的分布能力。Java 的 RMI 则在 RPC 的基础上向前又迈进了一步,即提供分布式对象间的通讯。
 (1)RMI框架
       【参考资料】
        《Java网络编程精解》孙卫琴,这本书适合入门学习RMI框架基础   
       RMI框架封装了所有底层通信细节,并且解决了编组、分布式垃圾收集、安全检查和并发性等通用问题。有了现成的框架,开发人员就只需专注于开发与特定问题领域相关的各种本地对象和远程对象。
      要了解RMI原理,先了解一下Stub和Skeleton两个概念。
(2)Stub和Skeleton
      RMI框架采用代理来负责客户与远程对象之间通过Socket进行通信的细节。RMI框架为远程对象分别生成了客户端代理和服务器端代理。位于客户端的代理类称为存根(Stub),位于服务器端的代理类称为骨架(Skeleton)。

 
    【相关资料】
     《RMI(Remote Method Invocation)初窥门径》 http://blog.csdn.net/smcwwh/article/details/7080997
     stub(存根)和skeleton(骨架)在RMI中充当代理角色,在现实开发中主要是用来隐藏系统和网络的的差异, 这一部分的功能在RMI开发中对程序员是透明的。Stub为客户端编码远程命令并把他们发送到服务器。而Skeleton则是把远程命令解码,调用服务端的远程对象的方法,把结果在编码发给stub,然后stub再解码返回调用结果给客户端。
     RMI远程过程调用的实现过程如下图所示:
     RMI 框架的基本原理大概如下图,应用了代理模式来封装了本地存根与真实的远程对象进行通信的细节
【参考资料】
    《Java RMI 框架(远程方法调用)》http://haolloyin.blog.51cto.com/1177454/332426

二、Java RMI 简单示例

    别急,慢慢分析~具体代码在下面,附例子代码下载:http://download.csdn.net/detail/guyuealian/9583633
大致说来,创建一个RMI应用包括以下步骤:
      (1)创建远程接口:继承java.rmi.Remote接口。
      (2)创建远程类:实现远程接口。
      (3)创建服务器程序:创建远程对象,通过createRegistry()方法注册远程对象。并通过bind或者rebind方法,把远程对象绑定到指定名称空间(URL)中。
      (4)创建客户程序:通过 lookup()方法查找远程对象,进行远程方法调用 
     下面具体分析每个步骤:
(1)创建远程接口:继承java.rmi.Remote接口。
       远程接口中声明了可以被客户程序访问的远程方法。RMI规范要求远程对象所属的类实现一个远程接口,并且远程接口符合以下条件:
       (a)直接或间接继承java.rmi.Remote接口。
       (b)接口中的所有方法声明抛出java.rmi.RemoteException。
(2)创建远程类:实现远程接口。
        远程类就是远程对象所属的类。RMI规范要求远程类必须实现一个远程接口。此外,为了使远程类的实例变成能为远程客户提供服务的远程对象,可通过以下两种途径之一把它导出(export)为远程对象:
       (a)导出为远程对象的第一种方式:使远程类实现远程接口时,同时继承java.rmi.server.UnicastRemoteObject类,并且远程类的构造方法必须声明抛出RemoteException。这是最常用的方式,下面的本例子就采取这种方式。
       (b)导出为远程对象的第二种方式:如果一个远程类已经继承了其他类,无法再继承UnicastRemoteObject类,那么可以在构造方法中调用UnicastRemoteObject类的静态exportObject()方法,同样,远程类的构造方法也必须声明抛出RemoteException。
        exportObject()是UnicastRemoteObject的静态方法,源码是:
 protected UnicastRemoteObject(int port) throws RemoteException
{
this.port = port;
exportObject((Remote) this, port);
}
 public static Remote exportObject(Remote obj, int port)
throws RemoteException
{
return exportObject(obj, new UnicastServerRef(port));
}

exportObject(Remote obj, int port),该方法负责把参数obj指定的对象导出为远程对象,使它具有相应的存根(Stub),并监听远程客户的方法调用请求;参数port指导监听的端口,如果值为0,表示监听任意一个匿名端口。
(3)创建服务器程序:创建远程对象,在rmiregistry注册表中注册远程对象,并绑定到指定的URL中。

       RMI采用一种命名服务机制来使得客户程序可以找到服务器上的一个远程对象。在JDK的安装目录的bin子目录下有一个rmiregistry.exe程序,它是提供命名服务的注册表程序。
      服务器程序的一大任务就是向rmiregistry注册表注册远程对象。从JDK1.3以上版本开始,RMI的命名服务API被整合到JNDI(Java Naming and Directory Interface,Java名字与目录接口)中。在JNDI中,javax.naming.Context接口声明了注册、查找,以及注销对象的方法:
    【1】 bind(String name,Object obj):注册对象,把对象与一个名字name绑定,这里的name其实就是URL格式。如果该名字已经与其它对象绑定,就会抛出NameAlreadyBoundException。
    【2】rebind(String name,Object obj):注册对象,把对象与一个名字绑定。如果该名字已经与其它对象绑定,不会抛出NameAlreadyBoundException,而是把当前参数obj指定的对象覆盖原先的对象。
    【3】 lookup(String name):查找对象,返回与参数name指定的名字所绑定的对象。
    【4】unbind(String name):注销对象,取消对象与名字的绑定。
     注册一个远程对象remoteObj2 关键代码如下:
     但在JDK1.3版本或更低的版本,需要使用java.rmi.Naming来注册远程对象,注册代码代替如下:

(4)创建客户程序:通过 lookup()方法查找远程对象,进行远程方法调用

关键代码如下:

在JDK1.3版本或更低的版本,如下方式调用;

例子具体代码:
   1. 创建远程接口:继承java.rmi.Remote接口。
       在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象, 供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”  (扩展 java.rmi.Remote 的接口)中指定的这些方法才可被远程调用。注意:接口中需要被远程调用的方法,必须抛出RemoteException异常。

2. 创建远程类:实现远程接口

      远程对象必须实现java.rmi.server.UniCastRemoteObject类,该类的构造函数中将生成stub和skeleton, 这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为Stub(存根), 而服务器端本身已存在的远程对象则称之为Skeleton(骨架)。其实此时的存根是客户端的一个代理,用于与服务器端的通信,  而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。
     3.创建服务器程序:在rmiregistry注册表中注册远程对象,向客户端提供远程对象服务  

在JDK1.3版本或更低的版本,如下方式注册;

     RMIServer类主要实现注册远程对象,并向客户端提供远程对象服务。远程对象是在远程服务上创建的,你无法确切地知道远程服务器上的对象的名称 。但是,将远程对象注册到RMI Service之后,客户端就可以通过RMI Service请求到该远程服务对象的stub了,利用stub代理就可以访问远程服务对象了 。

   4. 客户端代码

     Server端的代码已经全部写完,这时把服务器的接口RemoteInterface打包成jar,以便在Client端的项目中使用。
     项目-->右键-->导出-->jar->选择RemoteInterface.java-->finish;关于客户端如何导入jar包,请看这里:http://jingyan.baidu.com/article/ca41422fc76c4a1eae99ed9f.html
 package rmi2;
import javax.naming.Context;
import javax.naming.InitialContext; import rmi.RemoteInterface;
public class ClientTest {
public static void main(String args[]) {
try {
Context namingContext = new InitialContext();// 初始化命名内容
RemoteInterface RmObj2 = (RemoteInterface) namingContext
.lookup("rmi://localhost:8892/RemoteObj2");//获得远程对象的存根对象
System.out.println(RmObj2.doSomething());//通过远程对象,调用doSomething方法
System.out.println("远程服务器计算结果为:" + RmObj2.Calculate(90, 2));
} catch (Exception e) {
}
}
}

在JDK1.3版本或更低的版本,如下方式调用

输出结果:

JavaSE--RMI初识的更多相关文章

  1. JavaSE基础(一)--初识Java

    Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式 ...

  2. JavaSE教程-01初识Java

    1.计算机的概念 软件+硬件 2.操作系统 Windows.Mac.Linux.Unix等 3.计算机编程语言 计算机语言是一种人与计算机沟通的媒介. 分类: 机器语言:都是基于二进制的方式,由0和1 ...

  3. JavaSE教程-01初识Java-思维导图

    图片看不清楚时: 1)可以将图片另存为图片,保存在本地来查看 2)右击在新标签中打开放大查看. 分解: 1.计算机基本概念的普及 硬件 cpu.内存.硬盘等 软件 系统级软件 Windows.Linu ...

  4. JavaSE基础知识(1)—初识Java

    一.JAVA的背景 JAVA本身隶属的公司的是sun公司(创始公司) JAVA创始人:詹姆斯 高斯林 09年被oracle收购 JAVA的前身是Oak 二.JAVA的版本 95年 JAVA诞生96年 ...

  5. Java RMI之HelloWorld篇

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  6. 初识Java

    Java是一种简单的.面向对象的.分布式的.解释的.安全的.可移植的.性能优异的多线程语言.它以极强的安全性.平台无关性.硬件结构无关性.语言简洁.面向对象的特点,在网络编程语言中占据了无可比拟的优势 ...

  7. Java远程方法调用(Remote Method Invocation,RMI)

    Java RMI简介: 它是Java的一个核心API和类库,允许一个Java虚拟机上运行的Java程序调用不同虚拟机上运行的对象中的方法,即使这两个虚拟机运行于物理隔离的不同主机上. Java RMI ...

  8. Druid Monitor监控JavaSE,杀cmd端口进程

    1.需要在启动命令添加相关jvm参数 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname -Dcom.sun.management.jm ...

  9. Java初识

    基础概念 特点: 完全面向对象,动态 解释性,简单.易移植,跨平台 安全健壮,高性能 多线程,分布式 三种核心机制: Java虚拟机 Java Virtual Machine 垃圾收集机制 Garba ...

  10. 系统间通信(9)——通信管理与RMI 下篇

    接上文<架构设计:系统间通信(8)--通信管理与RMI 上篇>.之前说过,JDK中的RMI框架在JDK1.1.JDK1.2.JDK1.5.JDK1.6+几个版本中做了较大的调整.以下我们讨 ...

随机推荐

  1. kafka管理神器-kafkamanager

    好久没发过kafka的文章了,今天整理一下kafka-manager神器. java环境要求 jdk8 kafkamanager源码下载 https://github.com/yahoo/kafka- ...

  2. Apache NiFi Processor实战

    1 前言 Apache NiFi是什么?NiFi官网给出如下解释:“一个易用.强大.可靠的数据处理与分发系统”.通俗的来说,即Apache NiFi 是一个易于使用.功能强大而且可靠的数据处理和分发系 ...

  3. P1013 数素数

    转跳点:

  4. windows driver 延时

    #define Delay_One_MicroSecond (-10) #define Delay_One_MilliSecond (Delay_One_MicroSecond * 1000) voi ...

  5. 【LeetCode】二叉树的最大深度

    [问题]给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数.说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,null,15,7 ...

  6. Python学习——enumerate

    enumerate(seq, start) seq -- 可遍历的序列      start -- 下标起始位置 seq = [11,22,33,44,55] for i in seq: print( ...

  7. C# ASP 面试题 2017

    在博客上看到的,感觉还不错 https://www.cnblogs.com/renyiqiu/p/6435261.html

  8. 实验吧Web-中-让我进去(Hash长度扩展攻击、加盐密码及Linux下hashpump的安装使用)

    打开网页,测试开始,注入费老大劲,看了大佬的blog才知道怎么干. bp抓包,观察发现cookie中有个source=0,在repeater中修改为source=1,然go一下,出来了一段源代码. $ ...

  9. Invalid bound statement (not found): com.xxxx.dao.other.LoginDao.getUser"

    原来是能正常运行的,后想把登录相关的调整一下目录,对应登录的文件都调整到了other下边,启动服务,请求时报错: Invalid bound statement (not found): com.xx ...

  10. 基于百度语音识别API的Python语音识别小程序

    一.功能概述 实现语音为文字,可以扩展到多种场景进行工作,这里只实现其基本的语言接收及转换功能. 在语言录入时,根据语言内容的多少与停顿时间,自动截取音频进行转换. 工作示例: 二.软件环境 操作系统 ...