Java RMI详解

一丶RMI 定义
        RMI(Remote Method Invocation):远程方法调用。能够让某个 java 虚拟机上的对象调用运行在另一个 java 虚拟机上的对象的方法,就像调用本地方法一样。这两个虚拟机可以是运行在相同计算机上不同组件的不同进程中,也可以是运行在网络上不同计算机的当中,解决系统之间的通信问题。


二丶RMI调用时序图







三丶关于 RMI 的例子


客户端接口:

public interface HelloRmi extends Remote {

    public String sayHello() throws RemoteException;
}


接口实现:

public class HelloRmiImpl extends UnicastRemoteObject implements HelloRmi,Serializable {

    public HelloRmiImpl() throws RemoteException {
    }

    public String sayHello() throws RemoteException {
        return "Hello Rmi......";
    }
}

发布服务:

public class RmiServer {

    public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {


        HelloRmi rmi = new HelloRmiImpl();
        String url = publishService(rmi, "127.0.0.1", 1099);

        System.out.println("rmi service has bean started......");

    }

    // 发布 RMI 服务
    private static String publishService(Remote remote, String host, int port) {
        String url = null;
        try {
            /**
             * host 是注册表所在的主机(远程或本地)
             * port 是注册表接受调用的端口号,默认为 1099
             */
            url = String.format("rmi://%s:%d/%s", host, port, remote.getClass().getName());
            //创建并导出接受指定 port 请求的本地主机上的 Registry 实例
            LocateRegistry.createRegistry(port);
            // 将指定的名称 url 重新绑定到一个新的远程对象
            Naming.rebind(url, remote);
            System.out.println("publish rmi service,url: = " +  url);
        } catch (RemoteException e) {
            e.printStackTrace();
        }catch (MalformedURLException e) {
            e.printStackTrace();
        }

        return url;
    }
}

调用服务:

public class RmiClient {

    public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {

        String url= "rmi://127.0.0.1:1099/com.lai.rmi.server.HelloRmiImpl";
        //返回与指定名称 url 关联的远程对象的引用
        HelloRmi rmi = (HelloRmi) Naming.lookup(url);
        System.out.println(rmi.sayHello());
    }
}

四丶注意的细节


1丶因为方法的参数跟返回值最终都是会在网络上传输,所以实现必须是可序列化的

2丶UnicastRemoteObject类的构造函数抛出了RemoteException,故其继承类不能使用默认构造函数,继承类的构造函数必须也抛出RemoteException

3丶Registry 是简单远程对象注册表的一个远程接口,它提供存储和获取绑定了任意字符串名称的远程对象引用的方法

4丶Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口

5丶Skeleton(代理,学术名骨架)    Stub(代理):学术名存根。在服务端我们发布了RMI服务,并在JNDI中进行了注册,此时就在服务端创建了一个Skeleton,当客户端第一次成功连接JNDI并获取远程服务对象后,立马在本地创建了一个Stub

6丶远程通信实际是通过Skeleton与Stub来完成的,数据是基于TCP/IP协议


在服务端我们发布了RMI服务,并在JNDI中进行了注册,此时就在服务端创建了一个Skeleton(骨架),当客户端第一次成功连接JNDI并获取远程服务对象后,立马在本地创建了一个Stub(存根)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值