RMI简介
​ Java RMI,即 远程方法调用(Remote Method Invocation),一种用于实现远程过程调用(RPC)(Remote procedure call)的Java API, 能直接传输序列化后的Java对象和分布式垃圾收集。它的实现依赖于Java虚拟机(JVM),因此它仅支持从一个JVM到另一个JVM的调用。

rmi的实现
(1) 直接使用Registry实现rmi
服务端:

public class RegistryService {public static void main(String[] args) {try {// 本地主机上的远程对象注册表Registry的实例,默认端口1099Registry registry = LocateRegistry.createRegistry(1099);// 创建一个远程对象HelloRegistryFacade hello = new HelloRegistryFacadeImpl();// 把远程对象注册到RMI注册服务器上,并命名为HelloRegistryregistry.rebind("HelloRegistry", hello);System.out.println("======= 启动RMI服务成功! =======");} catch (RemoteException e) {e.printStackTrace();}}
}

接口:
继承Remote接口


public interface HelloRegistryFacade extends Remote {String helloWorld(String name) throws RemoteException;}

接口实现:
继承UnicastRemoteObject


public class HelloRegistryFacadeImpl extends UnicastRemoteObject implements HelloRegistryFacade{public HelloRegistryFacadeImpl() throws RemoteException {super();}@Overridepublic String helloWorld(String name) {return "[Registry] 你好! " + name;}}

客户端:

public class RegistryClient {public static void main(String[] args) {try {Registry registry = LocateRegistry.getRegistry(1099);HelloRegistryFacade hello = (HelloRegistryFacade) registry.lookup("HelloRegistry");String response = hello.helloWorld("ZhenJin");System.out.println("=======> " + response + " <=======");} catch (NotBoundException | RemoteException e) {e.printStackTrace();}}
}

图解:

Registry(注册表)是放置所有服务器对象的命名空间。
每次服务端创建一个对象时,它都会使用bind()或rebind()方法注册该对象。
这些是使用称为绑定名称的唯一名称注册的。要调用远程对象,客户端需要该对象的引用,如(HelloRegistryFacade)。
即通过服务端绑定的名称(HelloRegistry)从注册表中获取对象(lookup()方法)。

(2) 使用Naming方法实现rmi
服务端:

public class NamingService {public static void main(String[] args) {try {// 本地主机上的远程对象注册表Registry的实例LocateRegistry.createRegistry(1100);// 创建一个远程对象HelloNamingFacade hello = new HelloNamingFacadeImpl();// 把远程对象注册到RMI注册服务器上,并命名为Hello //绑定的URL标准格式为:rmi://host:port/nameNaming.bind("rmi://localhost:1100/HelloNaming", hello);System.out.println("======= 启动RMI服务成功! =======");} catch (RemoteException | MalformedURLException | AlreadyBoundException e) {e.printStackTrace();}}
}

接口和接口实现和Registry的方式一样

客户端:

public class NamingClient {public static void main(String[] args) {try {String remoteAddr="rmi://localhost:1100/HelloNaming";HelloNamingFacade hello = (HelloNamingFacade) Naming.lookup(remoteAddr);String response = hello.helloWorld("ZhenJin");System.out.println("=======> " + response + " <=======");} catch (NotBoundException | RemoteException | MalformedURLException e) {e.printStackTrace();}}
}

Naming部分源码:

public static Remote lookup(String name)throws NotBoundException,java.net.MalformedURLException,RemoteException{ParsedNamingURL parsed = parseURL(name);Registry registry = getRegistry(parsed);if (parsed.name == null)return registry;return registry.lookup(parsed.name);
}

Naming其实是对Registry的一个封装

Scala实现rmi
上面说了rmi是通过JVM虚拟机进行一个远程调用的,我们通过Scala,kotlin等jvm语言印证下

服务端:

object ScalaRmiService extends App {try {val user:UserScalaFacade = new UserScalaFacadeImplLocateRegistry.createRegistry(1103)Naming.rebind("rmi://localhost:1103/UserScala", user)println("======= 启动RMI服务成功! =======")} catch {case e: IOException => println(e)}
}

接口

trait UserScalaFacade extends Remote {/*** 通过用户名获取用户信息*/@throws(classOf[RemoteException])def getByName(userName: String): User/*** 通过用户性别获取用户信息*/@throws(classOf[RemoteException])def getBySex(userSex: String): List[User]}

接口实现:

class UserScalaFacadeImpl extends UnicastRemoteObject with UserScalaFacade {/*** 模拟一个数据库表*/private lazy val userList = List(new User("Jane", "女", 16),new User("jack", "男", 17),new User("ZhenJin", "男", 18))override def getByName(userName: String): User = userList.filter(u => userName.equals(u.userName)).headoverride def getBySex(userSex: String): List[User] = userList.filter(u => userSex.equals(u.userSex))}

实体类:
实体类必须实现序列化(Serializable)才能进行一个远程传输

class User(name: String, sex: String, age: Int) extends Serializable {var userName: String = namevar userSex: String = sexvar userAge: Int = ageoverride def toString = s"User(userName=$userName, userSex=$userSex, userAge=$userAge)"}

序列化简介
​ 序列化(Serialization)是将数据结构或对象状态转换为可以存储(例如,在文件或存储器缓冲区中)或传输(例如,通过网络连接)的格式的过程, 反序列化(Deserialization)则是从一系列字节中提取数据结构的相反操作.

SpringBoot实现rmi
StringBoot通过配置就可以简单实现rmi了

服务端:

@Configuration
public class RmiServiceConfig {@Beanpublic RmiServiceExporter registerService(UserFacade userFacade) {RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();rmiServiceExporter.setServiceName("UserInfo");rmiServiceExporter.setService(userFacade);rmiServiceExporter.setServiceInterface(UserFacade.class);rmiServiceExporter.setRegistryPort(1101);return rmiServiceExporter;}
}

客户端:

@Configuration
public class RmiClientConfig {@Beanpublic UserFacade userInfo() {RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();rmiProxyFactoryBean.setServiceUrl("rmi://localhost:1101/UserInfo");rmiProxyFactoryBean.setServiceInterface(UserFacade.class);rmiProxyFactoryBean.afterPropertiesSet();return (UserFacade) rmiProxyFactoryBean.getObject();}}

客户端测试类:

@Autowired
private UserFacade userFacade;@Test
public void userBySexTest() {try {List<User> userList = userFacade.getBySex("男");userList.forEach(System.out::println);} catch (RemoteException e) {e.printStackTrace();}
}

通过测试类可以看出,这和我们平时的程序调用内部方法没什么区别!

rmi调用过程

有两个远程服务接口可供client调用,Factory和Product接口

FactoryImpl类实现了Factory接口,ProductImpl类实现了Product接口

1. FactoryImpl被注册到了rmi-registry中
2. client端请求一个Factory的引用
3. rmi-registry返回client端一个FactoryImpl的引用
4. client端调用FactoryImpl的远程方法请求一个ProductImpl的远程引用
5. FactoryImpl返回给client端一个ProductImpl引用
6. client通过ProductImpl引用调用远程方法

【RMI】RMI详情介绍与使用!!!相关推荐

  1. 学计算机的学校17w,摇号中签率23.19%,学费一年17W?11所民校详情介绍!

    原标题:摇号中签率23.19%,学费一年17W?11所民校详情介绍! 民校专辑 点击蓝色字体查看学校具体介绍 2021小升初已经进入准备阶段,家长帮一路跟进小升初进度,帮助家长朋友搜集一手咨询,掌握最 ...

  2. 龙之谷哪个服务器最多,龙之谷哪些服务器数据互通 龙之谷数据互通详情介绍...

    类型:冒险解谜大小:633M语言:中文 评分:10.0 标签: 立即下载 龙之谷开放部分数据,小伙伴们部分服务器的数据能进行互通,因此不少小伙伴最关心的就是哪些服务器互通,不知道的小伙伴,就让小编给大 ...

  3. 汽车标定工具ETAS总线模块ES582.1详情介绍

    汽车标定工具ETAS总线模块ES582.1详情介绍 ETAS ES582.1 CAN FD总线接口USB模块(F-00K-110-731 ) 是 ETAS ES581.4 (F-00K-107-770 ...

  4. 搜狗微信为什么搜不到服务器,搜狗微信搜索部分功能为什么下线 搜狗微信搜索部分功能将被下线详情介绍...

    搜狗高速浏览器v7.0.6.23715 官方正式版 类型:浏览器类大小:45.0M语言:中文 评分:8.9 标签: 立即下载 最近不少小伙伴在使用搜狗浏览器进行搜索微信公众等关键词的时候都会出现10天 ...

  5. [转帖]兆芯发布国产X86处理器KX-6000和KH-30000,性能提升达50%,附详情介绍

    兆芯发布国产X86处理器KX-6000和KH-30000,性能提升达50%,附详情介绍 2019-06-20 09:56:38作者:linux人稿源:快科技 https://ywnz.com/linu ...

  6. 关于互相帮忙投票的微信群、微信刷投票群、微信投票刷票群的详情介绍

    关于互相帮忙投票的微信群.微信刷投票群.微信投票刷票群的详情介绍,当前很多微信投票活动慢慢变多,许多人在网上寻找关于"互相帮忙投票的微信群.微信刷投票群.微信投票刷票群"来自己拉票 ...

  7. lol服务器什么时候维护,lol等短时间维护是什么?lol11月23日服务器维护详情介绍...

    lol在线等短时间维护是什么?今天很多玩家都在反映lol出现了在线等短时间维护,这到底是什么意思呢?想了解的朋友可以来看看小编带来的lol11月23日服务器维护详情介绍,希望能帮到大家~ lol11月 ...

  8. 饥荒暴食活动服务器没有响应,饥荒暴食活动怎么玩?暴食活动玩法详情介绍

    饥荒暴食活动怎么玩?不了解饥荒暴食活动怎么玩的玩家,电玩之家小编为你准备了最新的图文攻略,感兴趣的玩家赶快一起来看看吧! 饥荒暴食活动玩法详情介绍 开局老羊会给10个金币,用6个金币买瓦罐锅,4个金币 ...

  9. 猿如意中的【Wireshark】网络包分析工具详情介绍

    一.工具名称 Wireshark-win64-3.6.5 二.下载安装渠道 Wireshark-win64-3.6.5 通过CSDN官方开发的[猿如意]客户端进行下载安装. 对,你没有看错,就是来自C ...

  10. Cubase 12新功能详情介绍

    Cubase 12新功能详情介绍:Steinberg Licensing 是向前迈出的一大步,是进一步发展我们为您带来最佳用户体验的愿景的重要里程碑.这种体验包括用于创作音乐的复杂工具.可使用的优质内 ...

最新文章

  1. 全球32家人工智能独角兽公司
  2. EchoServer
  3. 【白皮书】2020在线教育用户增长闭环白皮书.pdf(附下载链接)
  4. Linux问题---------E: 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用)
  5. 小程序“成语猜题”部分答案,总共28667题
  6. 2012 年上半年系统分析师 案例分析真题
  7. WebStorm使用-显示隐藏文件
  8. 常成员函数和静态成员函数
  9. 漫画脸软件哪个好?推荐这几款漫画脸软件
  10. B. Shifting Sort (思维)
  11. android sdl,能通吃所有安卓手机的SDL究竟是何神通?
  12. 存储模型之虚拟存储技术
  13. 10、刷牛客网SQL题(四)
  14. 满满干货!送给想学生物竞赛的同学们一份入门指南
  15. 宽带、专线等傻傻分不清楚——广域网协议
  16. 颠覆麦肯锡、BCG,这家公司的AI商业决策系统能做到吗?
  17. 【小学信息技术教资面试】《画多边形》教案
  18. 比特熊直播间一周年,英雄集结令!邀你来合影!
  19. 【无机纳米材料科研制图——OriginLab 0201】Origin光谱图、曲线图绘制
  20. springboot+vue漫画之家系统(源码+文档)

热门文章

  1. .有一千万条短信,有重复,以文本文件的形式保 请用5 分钟时间,找出重复出现最多的前10 条。
  2. 微信手机网页上传图片高效率压缩(Canvas+Base64)
  3. python+PIL批量制作淘宝主图(头图)及满屏水印添加
  4. java短信模板设计,全网疯传
  5. 两本参考书,垒四百块砖的日子
  6. 中秋节的广西甘蔗——智蔗见智·向新而生
  7. Java数据结构:图
  8. “大力丸”是壮阳药吗?
  9. 两条命令解决移动硬盘无法弹出的问题
  10. 太妙了!几个用Python给图片添加水印的方法,简单实用!