Java 远程方法调用,即 Java RMI( Java Remote Method Invocation ) 。顾名思义,可以使客户机上运行的程序能够调用远程服务器上的对象(方法)。

下面主要介绍一下使用步骤:

1.定义远程接口(服务端)

远程接口定义出可以让客户远程调用的方法。

此接口必须实现 java.rmi.Remote 接口,来表示其支持远程调用;同时其中声明的所有方法,需要抛出RemoteException异常,因为远程调用的不稳定性(如网络原因等),这样可以让客户端在调用失败时进行相应的处理。

public interface DemoService extends Remote {
String sayHello() throws RemoteException;
}

2.实现远程接口(服务端)

远程接口的实现类如果想要被远程访问,可以有如下实现方式:

继承java.rmi.server.UnicastRemoteObject

public class DemoServerImpl extends UnicastRemoteObject implements DemoService{

public DemoServerImpl() throws RemoteException {
// 因为 UnicastRemoteObject 构造器抛出 RemoteException
// 所以此处只能声明一个构造器并抛出对应异常
}

@Override
public String sayHello() throws RemoteException {
return "Hello World";
}
}

如果不想继承UnicastRemoteObject类,则需要使用 UnicastRemoteObject类的静态方法exportObject(Remote obj, int port)将对象导出

其中如果端口设为 0 的话,则表示任何合适的端口都可用来监听客户连接

public class DemoServerImpl implements DemoService{

public DemoServerImpl() throws RemoteException {
UnicastRemoteObject.exportObject(this, 0);
}

@Override
public String sayHello() throws RemoteException {
return "Hello World";
}
}

这两者方法本质上是一样的,在UnicaseRemoteObject类的构造方法中,其实也是调用了exportObject方法

// UnicaseRemoteObject中的部分源码
protected UnicastRemoteObject() throws RemoteException
{
this(0);
}
// if port is zero, an anonymous port is chosen
protected UnicastRemoteObject(int port) throws RemoteException
{
this.port = port;
exportObject((Remote) this, port);
}

3.启动 RMI 注册表

注册表就像一个电话簿,启动后即可将提供的服务注册到其中,客户可以通过它查询到服务来进行调用

启动注册表有两种方法,一种是通过命令行rmiregistry来启动,另一种方式是通过LocateRegistry.createRegistry(int port)方法。

4.注册开启远程服务

注册服务共有三种方式:

  1. LocateRegistry 类的对象的 rebind() 和 lookup() 来实现绑定注册和查找远程对象的

  2. 利用命名服务 java.rmi.Naming 类的 rebind() 和 lookup() 来实现绑定注册和查找远程对象的

  3. 利用JNDI(Java Naming and Directory Interface,Java命名和目录接口) java.naming.InitialContext 类来 rebind() 和 lookup() 来实现绑定注册和查找远程对象的

其中第二种方式实际是对第一种方式的简单封装,在内部仍是调用Registry类的bind方法

// Naming 类的部分源码 (为了节省篇幅,去除了抛出异常部分)
public static void bind(String name, Remote obj) throws ...
{
ParsedNamingURL parsed = parseURL(name);
Registry registry = getRegistry(parsed);

if (obj == null)
throw new NullPointerException("cannot bind to null");

registry.bind(parsed.name, obj);
}

服务测试类:

public class ServerTest {
public static void main(String[] args) throws Exception{
String name = "rmi.service.DemoService";
// 创建服务
DemoService service = new DemoServerImpl();
// 创建本机 1099 端口上的 RMI 注册表
Registry registry1 = LocateRegistry.createRegistry(1099); /***************** 以下为注册方法一 ************/
// 将服务绑定到注册表中
registry1.bind(name, service); /***************** 以下为注册方法二 ************/
// Naming.bind(name, service); /***************** 以下为注册方法三 ************/
//Context namingContext = new InitialContext();
//namingContext.bind("rmi:" + name, service); // 此方式 name 需要以 rmi: 开头 }
}

客户端测试类:

public class ClientTest {
public static void main(String[] args) throws Exception {
String name = "rmi.service.DemoService";
/***************** 以下为查找服务方法一 ************/
// 获取注册表
Registry registry = LocateRegistry.getRegistry("localhost", 1099);
// 查找对应的服务
DemoService service = (DemoService) registry.lookup(name); /***************** 以下为查找服务方法二 ************/
// DemoService service = (DemoService) Naming.lookup(name); /***************** 以下为查找服务方法三 ************/
//Context namingContext = new InitialContext();
//DemoService service = (DemoService) namingContext.lookup("rmi:" + name); // 调用服务
System.out.println(service.sayHello());
}
}

参考文章:https://segmentfault.com/a/1190000004494341

 

RMI 使用笔记的更多相关文章

  1. Java RMI 学习笔记

    概况 功能:提供了客户辅助对象和服务辅助对象,为客户辅助对象创建和服务辅助对象形同的方法. 优点:客户不必写任何网络或I/O代码,调用远程方法就和运行在客户自己的本地JVM上对对象进行的正常方法一样. ...

  2. Java的RMI远程方法调用实现和应用

    最近在学习Dubbo,RMI是很重要的底层机制,RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制.使用这种机制,某一 ...

  3. Java学习笔记(十六)——Java RMI

    [前面的话] 最近过的好舒服,每天过的感觉很充实,一些生活和工作的技巧注意了就会发现,其实生活也是可以过的如此的有滋有味,满足现在的状况,并且感觉很幸福. 学习java RMI的原因是最近在使用dub ...

  4. RMI笔记

    这是<java核心技术> 第11章 分布式对象的笔记. RMI基本原理 我们使用远程方法调用是希望达到这样的目的: 可以像调用本地方法一样去调用一个远程方法. 实现远程调用的方式是 为客户 ...

  5. Neo4j图数据库管理系统开发笔记之三:构建安全的RMI Service(Server)

    RMI Server(服务端)主要包括以下功能:远程用户权限验证管理.远程服务接口实现类.Neo4j实体映射转换等.项目目录结构如下图所示: 3.2.1 远程用户权限验证管理 3.2.1.1 用户权限 ...

  6. 关于JDK高版本下RMI、LDAP+JNDI bypass的一点笔记

    1.关于RMI 只启用RMI服务时,这时候RMI客户端能够去打服务端,有两种情况,第一种就是利用服务端本地的gadget,具体要看服务端pom.xml文件 比如yso中yso工具中已经集合了很多gad ...

  7. Linux 学习笔记

    Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...

  8. Docker 学习笔记(CentOS 7.1)

    基本概念 Docker 包括三个基本概念 镜像(Image) 容器(Container) 仓库(Repository)理解了这三个概念,就理解了 Docker 的整个生命周期. Docker 镜像 D ...

  9. kubernetes 内网节点部署笔记(一)

    在Centos7上部署kubernetes时,碰到很多坑,特别在摸拟在内网部署时,有来自GFW的障碍,有来自Firewalld的阻塞,反正是各种不服,终于慢慢理顺了思路,自己记录一下,防止遗忘. 环境 ...

随机推荐

  1. 内网渗透之信息收集-windows系统篇

    windows 用户相关 query user #查看当前在线的用户 whoami #查看当前用户 net user #查看当前系统全部用户 net1 user #查看当前系统全部用户(高权限命令) ...

  2. Java实现GBK转码到UTF-8(文件)

    所以,虚无的悲叹,寻根问底仍是由于肉身的圈定.肉身蒙蔽了灵魂的眼睛,单是看见要回那无中去,却忘了你原是从那无中来.                                            ...

  3. C语言程序设计(十一) 指针和数组

    第十一章 指针和数组 一旦给出数组的定义,编译系统就会为其在内存中分配固定的存储单元,相应的,数组的首地址也就确定了 C语言中的数组名有特殊的含义,它代表存放数组元素的连续存储空间的首地址 //L11 ...

  4. vue的$message(提示框换行)

    之前一直在搜怎么让提示框的文字换行,网上搜到的基本都是使用 ‘ /n ’,使用无效,也试了css换行,本来想用弹窗自己编辑html内容,还好回去官网看了一下: let arr = ['测试一', '测 ...

  5. 【tomcat系列】详解tomcat架构(上篇)

    java中,常用的web服务器一般由tomcat,weblogic,jetty,undertwo等,但从用户使用广泛度来说,tomcat用户量相对比较大一些,当然这也基于它开源和免费的特点. 从软件架 ...

  6. JavaScript(7)--- 继承

    JavaScript(7)--- 继承 概念 首先继承是一种关系,类(class)与类之间的关系,JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承,继承也是为了数据共享. 之间有讲过j ...

  7. C# 微信 生活助手 空气质量 天气预报等 效果展示 数据抓取 (二)

    此文主要是 中国天气网和中国环境监测总站的数据抓取 打算开放全部数据抓取源代码 已在服务器上 稳定运行半个月 webapi http://api.xuzhiheng.cn/ 常量 /// <su ...

  8. 免注册公众号的三种微信推送消息服务的C#代码实现

    有时候我们需要监控一些网络上的变化,但是每次去刷新网页却又很麻烦,而且大部分刷新的时候网页并没有更新.那么有没有一个工具,可以监控网页变化,并将变化的结果推送到手机微信上呢? 这里有很多应用场景,比如 ...

  9. xgboost安装与原理

    1.xgboost库的安装 先在网址https://www.lfd.uci.edu/~gohlke/pythonlibs/#xgboost 中下载whl文件,注意一定要下载跟自己当前安装Python版 ...

  10. css清除浮动影响

    将清除浮动代码添加到重置样式表中,随时可以调用 }}.clearfix:after{clear:both} 给需要清除浮动影响的元素添加class名 --- clearfix 例: <!-- c ...