RMI 深入探究

RMI深入探究

前面我们学习了RMI的一些基本知识,本节我们将深入理解RMI应用的基本架构并在此基础上构建自己的RMI应用程序。

RMI 应用架构

前面的文章,主要介绍了RMI框架的基本知识,本节我们将继续深入探讨RMI应用的架构及开发步骤,并深入理解这种架构的应用场景及优缺点。那就从下面这副图开始吧!下面这幅图是本人按照网络资料整理绘制的。这是我个人认为的RMI应用架构图:
在这里插入图片描述
根据上面这幅图,个人觉得有以下几点需要注意:

  1. Rmiregistry.exe应用主要完成远程对象的管理,即新增、删除、修改等
  2. Server服务端主要完成远程对象的注册
  3. Client服务主要从Rmiregistry.exe服务端查询远程对象,并利用其调用Server服务端的相关服务
  4. Rmiregistry.exe和Server代表的服务端程序可以部署在同一台服务器上(通常都会从安全角度出发,并考虑将这两者部署到同一台服务器上)。当然在最极端情况下也可以将Client、Rmiregistry.exe和Server部署到一台机器上

RMI 开发常用 API

根据前面整理的资料,我们知道RMI是Java版的RPC实现,所以Java提供了相关API以帮助开发者快速构建自己的小型分布式应用。常见的API有:

  1. Remote:这是一个接口,所有要发布的远程对象要继承这个接口
  2. UnicastRemoteObject:所有要发布的远程对象实现类都要继承这个类,继承这个类的本质是要调用这个类的静态方法export(Remote obj, int port)。如果远程对象实现类因为已经继承了某个类造成无法继承UnicastRemoteObject类,那么我们也可以通过在远程对象实现类的构造方法中直接调用UnicastRemoteObject类的export(Remote obj, int port)。这里有一点要注意:远程对象实现类的构造方法要抛出RemoteException异常
  3. Registry:这也是一个接口,其主要作用是完成远程对象的发布、删除、查询等操作。我们可以通过下述代码获取Registry对象:
Registry registry = LocateRegistry.createRegistry(1099);

当然除了用Registry完成远程对象的发布、删除、查询操作,我们还可以使用另外两个类完成同样的操作:1) java.rmi.Naming;2) javax.naming.Context(后面我们会展示这些类的具体用法)

构建自己的 RMI 应用

了解了RMI应用的基本架构,又学习了开发RMI应用的相关API,接下来我们就可以构建自己的RMI应用了。开发RMI应用主要分为以下几个步骤:

  1. 创建远程接口,继承RMI的关键接口java.rmi.Remote
  2. 创建远程类,实现远程接口
  3. 创建服务器程序,负责向RMI注册器中注册远程对象
  4. 创建客户程序,负责定位远程对象,并调用远程对象的方法

接下来我们将按照这个步骤创建自己的RMI应用。

1 创建远程接口

这里我们直接贴出代码,如下所示:

public interface RMIService extends Remote {
    int add(int a, int b) throws RemoteException;
}

注意:

  • 继承Remote接口是关键,并且其中的远程方法要抛出RemoteException异常
  • 我们也可以先定义接口A(其中要指定相关的远程方法),接着定义继承接口A的接口B,此时这个接口B就是远程接口,而A不是远程接口

2 创建远程类

public class RMIServiceImpl extends UnicastRemoteObject implements RMIService {
    public RMIServiceImpl() throws RemoteException {
    }
    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
}

注意:

  • 红色标注的是关键地方
  • 如果远程类因为已经继承了某个类,从而导致无法继续继承UnicastRemoteObject类,我们可以在远程类的构造方法中调用UnicastRemoteObject类的exportObject(Remote obj, int port)方法(该方法的主要作用是将当前对象导出为远程对象),但一定要注意该构造方法一定要抛出RemoteException异常或其父类

3 创建服务器程序

public class SimpleServer {
    public static void main(String[] args) {
        try {
            // 创建远程对象
            RMIService obj = new RMIServiceImpl();
            // 创建注册服务,同时指定其监听端口
            Registry registry = LocateRegistry.createRegistry(1099);
            // 调用Registry的bind方法向Registry服务中发布远程服务,并将其绑定到某个远程服务名称上,比如:RMIService
		   registry.bind("RMIService", obj);
           System.out.println("RMIService 已注册");
        } catch (Exception e) {
            System.out.println("RMIServiceImpl 发生异常:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

注意:

  • 红色标注的是关键地方
  • 正如前面所讲,除了Registry这种发布服务的方式外,还可以通过java.rmi.Naming和javax.naming.Context来完成这个操作

4 创建客户程序

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

关于RMI应用程序的几点思考

通过上一节,我们创建了一个属于自己的简单的RMI服务,但是这个服务有一些缺陷存在,比如:

  1. Rmiregistry.exe和Server代表的服务端程序部署于同一台服务器,那遇到服务其宕机,所以依赖于这个Rmiregistry的客户端将出现瘫痪,会对客户带来不好的体验
  2. 即使Rmiregistry与Server分开部署,服务器宕机,客户端就无法调用的情况依旧存在,因为Rmiregistry无法支持高可用部署(这种说法或许不对,但确实会有这种情况)
  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

机器挖掘工

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

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

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

打赏作者

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

抵扣说明:

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

余额充值