Java的RMI(远程方法调用)机制实现示例

概述

Java的远程方法调用(Remote Method Invocation,简称RMI)概念上是比较抽象的,它提供了一种机制,使得分布式环境下的Java对象可以在不同的JVM之间进行调用。
在Java RMI中,客户端请求远程服务器上的对象方法时,实际上是在客户端JVM中的代理生成了一个本地对象,该本地对象实际上是远程服务器上的对象的代理。客户端JVM通过JRMP协议连接到远程服务器上的JVM,然后调用远程对象的方法,将参数传递给远程对象,并获取远程对象方法的返回值。
它是一种用于实现分布式应用系统的技术,通过RMI可以使得客户端程序能够调用远程服务器中的Java对象方法,就如同在本地调用Java对象一样简单和自然。具体实现过程如下:

  1. 定义远程接口,包含需要远程调用的方法,接口必须要继承Remote接口。

  2. 实现远程接口,编写实现了远程接口的Java类,这个类的对象将作为服务端提供远程调用的Java对象。

  3. 创建远程对象,使用Java的Naming类或者RMI服务注册表(Java RMI Registry)提供的bind方法将创建实现了远程接口的Java对象注册到服务注册表中。

  4. 启动RMI服务,使用Java自带的rmiregistry命令或者rmi激活类(Activation)启动Java RMI注册表服务。

  5. 远程调用,客户端使用Lookup方法查找服务注册表中的远程对象,取得远程对象的引用,然后就可以通过这个引用调用远程对象提供的方法了。

RMI的优点是在Java中实现简单方便,调用方式与本地方法调用一致,而且可以通过Java的远程调用机制来提供应用程序的可扩展性和灵活性。同时,RMI还可以提供对象的传输、数据类型和格式转换、兼容性等多种功能,在Java分布式应用技术中具有重要地位。

RMI是基于什么网络协议的?

Java的RMI(Remote Method Invocation,远程方法调用)机制是基于Java Remote Protocol (JRMP)实现的。
JRMP是一种Java专用的协议,它是在Java虚拟机(JVM)级别上运行的,用于在分布式环境下的Java应用程序之间进行通信。JRMP协议是一种面向连接的、基于TCP/IP协议的协议,它建立在Java RMI框架之上。

实现

服务端代码:
远程接口

/**
 * 需要远程调用的方法的接口
 */
public interface RemoteService extends Remote {
    int add(int a, int b) throws RemoteException;
}

服务端

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

public class RemoteServiceImpl extends UnicastRemoteObject implements RemoteService {
    /**
     * 定义实现的远程方法
     */
    public RemoteServiceImpl() throws RemoteException {}

    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }

    public static void main(String[] args) {
        try {
            // 注册RMI服务
            RemoteService obj = new RemoteServiceImpl();
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.bind("RemoteService", obj);
            System.out.println("RemoteService已注册");
        } catch (Exception e) {
            System.out.println("RemoteServiceImpl发生异常:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

客户端代码:

import com.rqy.server.RemoteService;

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

public class RemoteClient {
    public static void main(String[] args) {
        try {
            // 获取远程对象
            Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);
            RemoteService obj = (RemoteService) registry.lookup("RemoteService");
            // 调用远程方法
            int result = obj.add(10, 20);
            System.out.println("远程调用结果:" + result);
        } catch (Exception e) {
            System.out.println("RemoteClient发生异常:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

在服务端启动RemoteServiceImpl,会在1099端口绑定注册远程服务,然后在客户端调用RemoteClient,通过registry.lookup(“RemoteService”)获取RemoteServiceImpl远程实例,并调用RemoteServiceImpl的add方法,最终返回结果。

可能在这里读者会疑惑,在服务端创建的RemoteService接口,怎么在客户端直接调用了?实际上是这样的,RemoteService是定义在服务端的RemoteService接口中的,而客户端需要使用该接口,因此在客户端代码中需要导入RemoteService接口所在的包。此处只是演示通信,所以服务端和客户端在同一个项目中,只是所属main不同,故而直接引用。但是读者应该要知道,在实际生产中,客户端和服务端是分开的,此接口需要通过引用服务端打的包才能成功引用 如果RemoteService接口和实现类都在服务端的同一个包中,那么客户端还需要将接口所在的包以一个JAR文件的形式打包,并将其放入服务端和客户端的类路径中,以便客户端能够访问接口;如果是在分布式系统中,那么也需要确保客户端和服务端的RemoteService接口的版本是一致的,并且客户端和服务端的类路径包含了RemoteService接口的定义。

请注意:为了使用该示例,需要确保在运行客户端之前,先将RemoteServiceImpl类加入到远程Java RMI注册表中。可以使用rmiregistry命令启动注册表,或者在IDE中启动一个可插入式的RMI注册表。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君去何方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值