写点什么

涨薪 20k!华为内部分享的 Java RMI 笔记爆火 Github,原理实践双飞

发布于: 2021 年 05 月 26 日
涨薪20k!华为内部分享的Java RMI笔记爆火Github,原理实践双飞

今日分享开始啦,请大家多多指教~


Java RMI:Java 远程方法调用,即 Java RMI(Java Remote Method Invocation)是 Java 编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使 Java 编程人员能够在网络环境中分布操作。RMI 全部的宗旨就是尽可能简化远程接口对象的使用。


我们知道远程过程调用(Remote Procedure Call, RPC)可以用于一个进程调用另一个进程(很可能在另一个远程主机上)中的过程,从而提供了过程的分布能力。Java 的 RMI 则在 RPC 在此基础上向前又迈进了一步,即提供分布式对象间的通讯。


RMI(Remote Method Invocation)为远程方法调用,是允许运行在一个 Java 虚拟机的对象调用运行在另一个 Java 虚拟机上的对象的方法。


这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中。

【JavaRMI】

一、工作原理

RMI 能让一个 Java 程序去调用网络中另一台计算机的 Java 对象的方法,那么调用的效果就像是在本机上调用一样。通俗地讲:A 机器上面有一个 class,通过远程调用,B 机器调用这个 class 中的方法。


RMI,远程方法调用(Remote Method Invocation)是 Enterprise JavaBeans 的支柱,是建立分布式 Java 应用程序的方便途径。RMI 是非常容易使用的,但是它非常的强大。


RMI 的基础是接口,RMI 构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。下面我们通过具体的例子,建立一个简单的远程计算服务和使用它的客户程序。

二、RMI 包含部分:

  1. 远程服务的接口定义

  2. 远程服务接口的具体实现

  3. 桩(Stub)和框架(Skeleton)文件

  4. 一个运行远程服务的服务器

  5. 一个 RMI 命名服务,它允许客户端去发现这个远程服务

  6. 类文件的提供者(一个 HTTP 或者 FTP 服务器)

  7. 一个需要这个远程服务的客户端程序

三、RMI 的用途?

RMI 的用途是为分布式 Java 应用程序之间的远程通信提供服务,提供分布式服务。

目前主要应用是封装在各个 J2EE 项目框架中,例如 Spring,EJB(Spring 和 EJB 均封装了 RMI 技术)


在 Spring 中实现 RMI:

①在服务器端定义服务的接口,定义特定的类实现这些接口;

②在服务器端使用 org.springframework.remoting.rmi.RmiServiceExporter 类来注册服务;

③在客户端使用 org.springframework.remoting.rmi.RmiProxyFactoryBean 来实现远程服务的代理功能;

④在客户端定义访问与服务器端服务接口相同的类

四、RMI 的局限?

RMI 目前使用 Java 远程消息交换协议 JRMP(Java Remote Messaging Protocol)进行通信。JRMP 是专为 Java 的远程对象制定的协议,由于 JRMP 是专为 Java 对象制定的,因此,RMI 对于用非 Java 语言开发的应用系统的支持不足。不能与用非 Java 语言书写的对象进行通信(意思是只支持客户端和服务器端都是 Java 程序的代码的远程调用)。

五、RMI 的使用局限?

由于客户机和服务器都是使用 Java 编写的,二者平台兼容性的要求仅仅是双方都运行在版本兼容的 Java 虚拟机上。

六、RMI 调用远程方法的参数和返回值

当调用远程对象上的方法时,客户机除了可以将原始类型的数据作为参数以外,还可以将对象作为参数来传递,与之相对应的是返回值,可以返回原始类型或对象,这些都是通过 Java 的对象序列化(serialization)技术来实现的。(换而言之:参数或者返回值如果是对象的话必须实现 Serializable 接口)

七、 RMI 应用程序的基本模型

八、RMI 体系结构

桩/框架(Stub/Skeleton)层:客户端的桩和服务器端的框架;

远程引用(remote reference)层:处理远程引用行为

传送层(transport):连接的建立和管理,以及远程对象的跟踪

九、 RMI 类和接口(完成一个简单 RMI 需要用到的类)。

(一) Remote 接口:是一个不定义方法的标记接口

Public interface Remote{}

在 RMI 中,远程接口声明了可以从远程 Java 虚拟机中调用的方法集。远程接口满足下列要求:

1、远程接口必须直接或间接扩展 Java.rmi.Remote 接口,且必须声明为 public,除非客户端于远程接口在同一包中

2、在远程接口中的方法在声明时,除了要抛出与应用程序有关的一场之外,还必须包括 RemoteException(或它的超类,IOExcepion 或 Exception)异常

3、在远程方法声明中,作为参数或返回值声明的远程对象必须声明为远程接口,而非该接口的实现类。

(二) RemoteObject 抽象类实现了 Remote 接口和序列化 Serializable 接口,它和它的子类提供 RMI 服务器函数。

(三) LocateRegistry final()类用于获得特定主机的引导远程对象注册服务器程序的引用(即创建 stub),或者创建能在特定端口接收调用的远程对象注册服务程序。

服务器端:向其他客户机提供远程对象服务

SomeService servcie=……;//远程对象服务

  1. Registry registry=LocateRegisty.getRegistry();//Registry 是个接口,他继承了 Remote,此方法返回本地主机在默认注册表端口 1099 上对远程对象 Registry 的引用。

  2. getRegistry(int port) 返回本地主机在指定 port 上对远程对象 Registry 的引用;

  3. getRegistry(String host) 返回指定 host 在默认注册表端口 1099 上对远程对象 Registry 的引用;

  4. getRegistry(String host, int port) 返回指定的 host 和 port 上对远程对象 Registry 的引用

  5. registry.bind(“I serve”,service);// bind(String name,Remote obj) 绑定对此注册表中指定 name 的远程引用。name : 与该远程引用相关的名称 obj : 对远程对象(通常是一个 stub)的引用

  6. unbind(String name)移除注册表中指定 name 的绑定。

  7. rebind(String name,Remote obj)重新绑定,如果 name 已存在,但是 Remote 不一样则替换,如果 Remote 一样则丢弃现有的绑定

  8. lookup(String name) 返回注册表中绑定到指定 name 的远程引用,返回 Remote

  9. String[] list() 返回在此注册表中绑定的名称的数组。该数组将包含一个此注册表中调用此方法时绑定的名称快照。

客户机端:向服务器提供相应的服务请求。

Registry registry=LocateRegisty.getRegistry();

SomeService servcie=(SomeService)registry.lookup(“I serve”);

Servcie.requestService();

(四) Naming 类和 Registry 类类似。

客户端:

服务器端:

(五) RMISecurityManager 类

在 RMI 引用程序中,如果没有设置安全管理器,则只能从本地类路径加载 stub 和类,这可以确保应用程序不受由远程方法调用所下载的代码侵害

在从远程主机下载代码之前必须执行以下代码来安装 RMISecurityManager:

System.setSecurityManager(new RMISecurityManager());

十、demo 开发

为了编写一个 demo,我们分为两部分,一部分是 server 端的代码,一部分是 client 端的代码,client 端的代码主要是为了使用 server 端的代码。当然这个代码是非常简单的,只是为了说明问题,现实的使用会使比较复杂的。

(一) 我们的目的

建立一个 server 端的 java project,包含远程端的代码,定义接口,定义接口实现,然后再建立一个 client 端的 java project,通过 RMI 使用远端服务中的方法。

(二) 我们的代码结构

(三) 远程服务代码

1. 远程服务的接口定义

第一步就是建立和编译服务接口的 Java 代码。这个接口定义了所有的提供远程服务的功能,下面是源程序:UserManagerInterface.java

接口必须继承 Remote 类,每一个定义的方法都要抛出 RemoteException 异常对象。

2. 接口的具体实现

第二步就是对于上面的接口进行实现:

UserManagerImp.java

3.定义一个 bean,实现 implements Serializable 序列化接口。也就是可以在 client 和 server 端进行传输的可序列化对象。

Account.java

4. 定义 server 端的主程序入口。

Entry.java

(四) client 端代码

  • 把 Server 端的 Account 类和接口 UserManagerInterface 导出 Export 成 jar 包,命名为:RmiServerInterface.jar。导入到 client 中。

  • 项目——右键——Export——java——jar file——next——选择 Account 类和接口 UserManagerInterface——命名为:RmiServerInterface.jar 如下图:

  • 新建一个 java Project,导入 jar 包,编写客户端代码。

  • 代码

ClientEntry.java


  • 先运行服务器端代码, 然后运行客户端代码,就会显示运行结果,客户端可以运行多次,每次都可以取得服务器端的对象。如果要再次运行客户端代码就需要更改端口号,如果不更改就会显示端口号被占用。


今日份分享已结束,请大家多多包涵和指点!

用户头像

还未添加个人签名 2021.04.20 加入

Java工具与相关资料获取等WX: pfx950924(备注来源)

评论

发布
暂无评论
涨薪20k!华为内部分享的Java RMI笔记爆火Github,原理实践双飞