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. 借助Redis完成延时任务

    背景 相信我们或多或少的会遇到类似下面这样的需求: 第三方给了一批数据给我们处理,我们处理好之后就通知他们处理结果. 大概就是下面这个图说的. 本来在处理完数据之后,我们就会马上把处理结果返回给对方, ...

  2. Linux启动nginx时报错nginx: [emerg] getpwnam("nginx") failed

    编译时指定了用户而没有创建用户导致报错 解决: 查看你添加的用户是什么, [root@localhost nginx]# sbin/nginx -Vnginx version: nginx/1.10. ...

  3. Hadoop集群搭建(一)~虚拟机的创建

    Hadoop集群的搭建包括,虚拟机系统的安装:安装JDK,Hadoop:克隆虚拟机:伪分布式的搭建:安装zookeeper:Hive:Hbae:Spark等等: 我将分为多篇文章来记录.这篇文章主要写 ...

  4. gulp常用的插件

    参考地址: http://www.cnblogs.com/1wen/p/5421212.html https://my.oschina.net/wolfx/blog/673905 http://www ...

  5. tf.slice()函数详解(极详细)

    目录 1.官方注释 2.参数解释 3.例子 参考 @(tf.slice()函数详解 ) tf.slice()是TensorFlow库中分割张量的一个函数,其定义为def slice(input_, b ...

  6. 264. 丑数 II

    编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n = 10输出: 12解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 ...

  7. python高阶函数&异常处理

    高阶函数 1.什么是高阶函数 在Python中,变量可以指向函数 函数名也是变量 既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数. ma ...

  8. Flutter配置环境报错“PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”

    背景:最近看了很多Flutter漂亮的项目,想要尝试一下.所有环境都搭建好之后,按照文档一步一步配置(抄袭),但始终报如下图错误. PKIX path building failed: sun.sec ...

  9. angular 项目中遇到rxjs error TS1005:';'

    因为rxjs的版本问题,只需要在package.json 中将依赖的 rxjs:'^6.00' 改为 rxjs'6.00', 然后执行 npm update 更新下rxjs的依赖版本即可解决

  10. python-模块的发布和安装

    当我们 import python 模块时,默认先在当前路径搜索,如果当前路径找不到目标模块,python会到安装目录找,还找不到则抛出异常. 如果我们想让自己写的模块,能跟系统自带模块一样,在任何地 ...