Java RMI 远程方法调用

1 什么是 RMI

  • 我们说的 RMI 一般都是指 Java RMI
  • Remote Method Invocation:远程方法调用
  • 使一个 Java 虚拟机中的对象可以调用另一个 Java 虚拟机上的对象的方法(就像调用本地对象方法一样)
  • 两个虚拟机可以运行在同一机器中的不同进程中,也可以运行在网络上的其它机器中

2 RMI 的适用场景

  • 当需要远程调用另一个虚拟机中的对象方法时(必须两端都是 Java 应用)

3 为什么要用 RMI

  • RMI 封装了所有底层通信细节,使得开发人员只需专注于开发业务功能

4 RMI 核心概念

4.1 RMI 实现过程

在这里插入图片描述

4.2 Skeleton及Stub获取
  • 通过继承 UnicastRemoteObject 类,即可隐式的获取 Skeleton及Stub
  • 通过 rmic 工具生成:rmic xx.class,将生成 xx_Stub.class,xx_Skel.class(不推荐),UnicastRemoteObject 首先判断是否有静态的存根类,如果没有才动态创建 Stub

5 示例代码

//Remote 接口是一个标志接口,标志这个接口中所包含的方法从非本地虚拟机上调用
public interface StudentService extends Remote {
    //由于方法会通过网络调用,所以必须抛出 远程异常来说明该方法有风险
    Student getStudentList() throws RemoteException;
}
public class StudentServiceImpl extends UnicastRemoteObject implements StudentService {
    @Override
    public Student getStudentList() {
        return new Student(1,"wk");
    }
    // 该构造期必须存在,因为集继承了UnicastRemoteObject类,其构造器要抛出RemoteException
    public StudentServiceImpl() throws RemoteException {
        super();
    }
}
public class StudentServer {
    public static void main(String[] args) throws Exception{
        //创建一个远程对象,实质上隐含了是生成stub和skeleton,并返回stub代理引用
        StudentService stu = new StudentServiceImpl();
        StudentService stu0 = new StudentServiceImpl0();
        //在本地主机上创建和导出注册表实例,并在指定的端口上接受请求
        //Java默认端口是1099,缺少注册表创建,则无法绑定对象到远程注册表上
        LocateRegistry.createRegistry(1099);

        //把远程对象注册到RMI注册服务器上----------

        //JDK 1.3及以下
        //Naming.rebind("stu",stu);//绑定的URL标准格式为:rmi://host:port/name(其中rmi://host:port都可以省略)

        //JDK 1.3 以上
        Context namingContext = new InitialContext();//初始化命名上下文
        //把远程对象注册到RMI注册服务器上,注意:rmi 协议名不能省略,host:port可以省略
        namingContext.rebind("rmi:stu",stu);
        namingContext.rebind("rmi:stu0",stu0);
        System.out.println("服务器已启动!");

    }
}
public class StudentClient {
    public static void main(String[] args) throws Exception{
            //两种方式都可以获得远程对象
            StudentService stu = (StudentService) Naming.lookup("stu");
            Context namingContext = new InitialContext();
            StudentService stu0 = (StudentService) namingContext.lookup("rmi:stu");
            System.out.println(stu0.getStudentList().toString());
            System.out.println(stu.getStudentList().toString());

        StudentService stu01 = (StudentService) namingContext.lookup("rmi:stu0");
        System.out.println(stu01.getStudentList().toString());

    }
}

参考

github 源码地址
stub 和 skeleton 的讲解,自己实现一个stub和skeleton程序
RMI 报错:javax.naming.NoInitialContextException: specify class name environment system property
Java RMI远程方法调用详解
java项目中rmi远程调用实例
RMI底层实现原理
从懵逼到恍然大悟之Java中RMI的使用
Head First 设计模式 —— 代理模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值