java RMI 技术介绍和实践

news2024/11/24 4:35:17

        在项目上发现了使用rmi技术,充电一波

RMI 概述

        RMI(Remote Method Invocation)是一种 Java 编程语言中的远程过程调用(RPC)协议,用于在不同的Java虚拟机(JVM)之间进行通信和交互。它允许远程计算机上的Java对象像本地对象一样进行访问和操作,从而使分布式应用程序的开发变得更加容易和方便。

RMI 基本思想

        RMI 基本思想是远程方法调用,即客户端调用某个方法,其本质是将这个方法的调用请求,发送给服务器,由服务器代为执行,且,服务器将执行结果回送客户端。

  • 对于客户端而言,RMI 只要求客户端针对方法本身,产生一种错觉:方法是在本地被调用的;
  • 对于服务器而言,RMI 相当于要处理一个来自客户端的“请求”;这个请求针对某个方法。

RMI 设计分析

客户端功能:

  1. 连接 RMI 服务器;
  2. 远程方法的消费者,从Registry获取远程方法的相关信息并且调用
  3. 等待服务器返回这个方法在服务器端执行的结果。

服务器端功能:

  1. 建立 RMI 服务器;
  2. 侦听客户端连接请求;
  3. 连接 RMI 客户端;
  4. 接受客户端发送过来的要执行的方法名称、实参等信息;找到这个需要代理执行方法,并反射机制执行该方法,并将方法执行的结果回传给客户端,断开与客户端的连接。

Registry:

        提供服务注册与服务获取。即Server端向Registry注册服务,比如地址、端口等一些信息,Client端从Registry获取远程对象的一些信息,如地址、端口等,然后进行远程调用。

工作流程:

  1. 首先,启动RMI Registry服务,启动时可以指定服务监听的端口,也可以使用默认的端口(1099);

  2. 其次,Server端在本地先实例化一个提供服务的实现类,然后通过RMI提供的Naming/Context/Registry等类的bindrebind方法将刚才实例化好的实现类注册到RMI Registry上并对外暴露一个名称;

  3. 最后,Client端通过本地的接口和一个已知的名称(即RMI Registry暴露出的名称),使用RMI提供的Naming/Context/Registry等类的lookup方法从RMI Service那拿到实现类。这样虽然本地没有这个类的实现类,但所有的方法都在接口里了,便可以实现远程调用对象的方法了;

Demo

定义一个接口

package com.cjian.rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * @Author: cjian
 * @Date: 2023/11/8 10:17
 * @Des:
 */
public interface PersonController extends Remote {
    // 注意这里必须抛出RemoteException,否则在查找服务的时候会提示 illegal remote method encountered 异常
    String queryName() throws RemoteException;
}

服务端有上面接口的具体实现,这里实现main方法运行

package com.cjian.rmi;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;

/**
 * @Author: cjian
 * @Date: 2023/11/8 10:17
 * @Des:
 */
public class PersonControllerImpl extends UnicastRemoteObject implements PersonController {

    protected PersonControllerImpl() throws RemoteException {
    }

    @Override
    public String queryName() {
        System.out.println("Receive request");
        return "My name's CJ";
    }

    public static void main(String[] args) {
        try {
            //创建服务端
            PersonController personController = new PersonControllerImpl();
            //注册到8888端口,也注册可以注册到别的机器上。
            LocateRegistry.createRegistry(8888);
            //绑定服务端到指定的地址,这里的localhost对应的上一步注册端口号的机器
            java.rmi.Naming.rebind("rmi://localhost:8888/" + PersonController.class.getName(), personController);
            System.out.println("Ready...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

启动:

客户端调用

package com.cjian.rmi;

import java.rmi.Naming;

/**
 * @Author: cjian
 * @Date: 2023/11/8 10:21
 * @Des:
 */
public class ClientTest {
    public static void main(String[] args) {
        try {
            //客户端去查找指定的服务
            PersonController personController = (PersonController) Naming.lookup("rmi://localhost:8888/" + PersonController.class.getName());
            //打印的结果应该是 My name's CJ
            System.out.println(personController.queryName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试结果:

另一种写法:

package com.cjian.rmi.custom;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * @Author: cjian
 * @Date: 2023/11/8 10:17
 * @Des:
 */
public interface PersonController2 extends Remote {
    // 注意这里必须抛出RemoteException,否则在查找服务的时候会提示 illegal remote method encountered 异常
    String queryName() throws RemoteException;
}
package com.cjian.rmi.custom;

import com.cjian.rmi.PersonController;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

/**
 * @Author: cjian
 * @Date: 2023/11/8 10:17
 * @Des:
 */
public class PersonControllerImpl2 implements PersonController {

    @Override
    public String queryName() {
        System.out.println("Receive request");
        return "My name's CJ";
    }

    public static void main(String[] args) {
        try {
            //创建服务端
            PersonController personController = new PersonControllerImpl2();
            //注册到8888端口,也注册可以注册到别的机器上。
            UnicastRemoteObject.exportObject(personController, 8080);
            Registry registry = LocateRegistry.createRegistry(8888);
            registry.rebind(PersonController.class.getName(), personController);
            System.out.println("Ready...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.cjian.rmi.custom;

import com.cjian.rmi.PersonController;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

/**
 * @Author: cjian
 * @Date: 2023/11/8 10:21
 * @Des:
 */
public class ClientTest2 {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost", 8888);
            PersonController personController = (PersonController) registry.lookup(PersonController.class.getName());
            System.out.println(personController.queryName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

效果一样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1184226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于非精确线搜索算法三准则实现步长因子的求解

0、前言 朋友请我帮他做一个他们老师留的课堂作业,就自学了一下,我给他做了A准则和G准则的,W准则的留给他自己改了,也没有多难就是换一个判断条件就行了。 一、问题描述 二、要求 三、代码 3.1A准则加回退法 %帮别人做的小作业…

『MySQL快速上手』-⑤-数据类型

文章目录 1.数据类型有哪些2.数值类型2.1 tinyint 类型2.2 bit 类型2.3 小数类型2.3.1 float2.3.2 decimal 3.字符串类型3.1 char3.2 varchar3.2 char 和 varchar 比较 4.日期和时间类型5.enum和set 1.数据类型有哪些 MySQL支持多种数据类型,这些数据类型可用于定义…

第二证券:“闻”A股:注册制走深走实是活跃市场制度保障

不久前举办的中心金融工作会议明确要求“推动股票发行注册制走深走实”,无疑为本钱商场活泼进一步夯实制度保证。 上市公司是本钱商场的基石,其质量是决议本钱商场长期健康展开的重要因素之一。作为牵一发而动全身的重要革新,注册制的实施逐…

Pycharm加载项目时异常,看不到自己的项目文件

最近看到一个朋友问,他把项目导入pycharm为什么项目里的包不在项目里显示,只在projects file里显示?问题截图如下: Project里看不到自己的项目文件 只能在Project Files里看到自己的项目文件 问题解答 我也是偶然发现的这个方案…

CV计算机视觉每日开源代码Paper with code速览-2023.11.6

精华置顶 墙裂推荐!小白如何1个月系统学习CV核心知识:链接 点击CV计算机视觉,关注更多CV干货 论文已打包,点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【点云3D目标检测】(NeurIPS2023)…

NR SRS carrier switching

这篇看下SRS carrier switching的内容,这个feature 最早是LTE上提出的,在NR R15就引入了。个人没见过支持这个feature的UE,不过还是简单看下。 下面内容参照的是R17版本协议,顺序是背景->相关IE的配置结构及含义->DCI format 2_3->38.214中有关SRS carrier swtich…

代码随想录算法训练营第四十六天丨 动态规划part09

198.打家劫舍 思路 如果刚接触这样的题目,会有点困惑,当前的状态我是偷还是不偷呢? 仔细一想,当前房屋偷与不偷取决于 前一个房屋和前两个房屋是否被偷了。 所以这里就更感觉到,当前状态和前面状态会有一种依赖关系…

使用数据分析,识别设备异常

设备健康监测系统在工业领域中扮演着至关重要的角色,它能够帮助企业及时发现设备异常,预防故障,提高设备使用寿命和生产效率。而异常诊断技术则是设备健康监测系统中的核心部分,能够实现对设备异常情况的准确判断。根据设备状态数…

05预测识别-依托YOLO V8进行训练模型的识别——对视频中的目标进行跟踪统计

上文中详细介绍了如何对视频进行抽帧,并对帧的图像进行目标识别。但在日常工作中,我们也会遇到需要对目标进行跟踪统计的情况,比如我们需要连续统计某一类目标有多少个的时候,如果单纯从帧中抽取图像的话,系统将无法判断是否为同一目标,从而造成目标数量统计的重复,导致…

研发效能认证学员作品:持续集成与持续部署:软件高质量的关键丨IDCF

作者:李明君(现就职某金融机构) 研发效能(DevOps)工程师(中级)认证 在当今数字化时代,软件开发已经成为几乎所有行业的核心。随着市场的快速变化和客户需求的不断演进,软…

三国志14信息查询小程序(历史武将信息一览)制作更新过程06-复现小程序

0,所需文件 所需全部文件下载 文件总览: 代码: 数据库: 1,前期准备 假定你已经看过前面的文章,并完成了下列准备: (1)一台有公网IP的云服务器,服务器上…

day63--单调栈3

第一题:柱状图中最大的矩形 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 直接单调栈: 接雨水利用的是3个柱子形成一个凹槽…

Power Apps-使用用户信息

插入一个文本组件,点击该组件,点击右侧边栏中的文本,在上方函数中写入如下内容就可以获取到用户信息了 "Hello!"&User().FullName//字符串拼接

华为交换机端口 access、trunk和hybrid收发数据规则

文章目录 1. 三个端口类型处理数据帧的汇总表2. access 端口3. trunk端口4. Hybrid 端口(交换机的默认端口类型)常用命令 1. 三个端口类型处理数据帧的汇总表 端口类型收到不带VLAN标签的帧的处理规则收到带VLAN标签的帧的处理规则发送帧时的处理规则用…

利用AI快速跨过新手区:用DevChat编写Python程序-CSV导入TDengine

还在用百度搜索编程吗? 直接上 AI,帮助小白快速跨过新手区。 以下用一个物联网最常见的场景做示例演示如何利用 AI 快速编程。 ChatGPT4 是目前最火的 AI 了,但是国内却用不了。不过现在新出的 DevChat 可以让大家尝鲜一番。 以下介绍来自B…

rabbitmq入门学习

写在前面 本文看下rabbit mq的基础概念以及使用。 1:简单介绍 为了不同进程间通信的解耦,出现了消息队列,为了规范消息队列的具体实现,Java制定了jms规范,这是一套基于接口的规范,因此是绑定语言的&…

Xcode15更新内容

参考博客: 【WWDC 2023】Xcode 15 更新内容 文章目录 1. xcode15起,项目内创建的图片可以使用点语法访问2.2. UIKit项目也可以使用预览功能3. Xcode新增标签功能4.Log分类 1. xcode15起,项目内创建的图片可以使用点语法访问 2.2. UIKit项目也…

台达PLC和触摸屏之间无线MODBUS通讯

今天,我们来一起学下下台达PLC与触摸屏之间无线通信的实现方法。其中触摸屏作为主站,台达PLC作为从站,并采用日系PLC专用无线通讯终端DTD435MC,作为实现无线通讯的硬件设备。 台达PLC和触摸屏通讯关键是对于通讯参数的设置。 触…

C++入门学习(4)引用 (讲解拿指针比较)

上期回顾 在学习完函数重载之后,我们可以使用多个重名函数进行操作,会发现C真的是弥补了好多C语言的不足之处,真的不禁感概一下,时代的进步是需要人去做出改变的,而不是一味的使用啊!所以我们今天继续学一下…

从白日梦到现实:推出 Elastic 的管道查询语言 ES|QL

作者:George Kobar, Bahubali Shetti, Mark Settle 今天,我们很高兴地宣布 Elastic 的新管道查询语言 ES|QL(Elasticsearch 查询语言)的技术预览版,它可以转换、丰富和简化数据调查。 ES|QL 由新的查询引擎提供支持&am…