• 豫园商城升级改造:这些楼顶可见最好的风景--旅游频道 2019-05-14
  • 头条 —频道 春城壹网 七彩云南 一网天下 2019-05-14
  • 人为某种意识而奋斗是幸福的,获得成绩或成就更幸福。 2019-05-10
  • 【专题】省违反中央八项规定精神和“四风”问题线索举报平台 2019-05-09
  • 确定这是热身赛?吴前拼到大腿抽筋 拆绷带继续干 2019-05-09
  • 应对排放新规 大众德国工厂计划短暂停产 2019-04-26
  • 一师一团土地确权登记颁证工作全面展开 2019-04-26
  • 一语惊坛(5月31日):“我们不一样”,中国向世界许下一个承诺。 2019-04-22
  • 俄罗斯世界杯F组:球迷风采 2019-04-10
  • 5月份国民经济数据发布:中国经济持续稳中向好 2019-04-10
  • 贵州宣讲十九大:干部争当宣讲员 群众心窝暖洋洋 2019-03-25
  • 别空谈,说说看,这个“简单的逻辑关系”是什么关系? 2019-03-25
  • 快过闪电,MIUI 10与MIUI 9速度对比 2019-03-21
  • 泽州去年“免费教育”资金达5211万元 2019-03-19
  • 看你这么可怜,再提示你一下:你重孙算1,父母为2,父母的父母为4,父母的父母的父母为8…… 2019-03-19
  • 【杂谈】对RMI(Remote Method Invoke)的认识

    前言

    快乐彩开奖号码 www.752o.com   对RMI接触的也比较早,基本上刚学完Java基础不久就机缘巧合遇到了。当时有尝试着去了解,但是没看到比较好的教程,而且对网络编程相关知识不太了解,看了不少文章,也没弄明白。现在对网络和I/O有了一定了解,理解起来也比较顺畅了。以下,是我对RMI的认识。

    RMI的相关概念

      "In computing, the Java Remote Method Invocation (Java RMI) is a Java API that performs remote method invocation, the object-oriented equivalent of remote procedure calls (RPC), with support for direct transfer of serialized Java classes and distributed garbage-collection." ——维基百科

      上述定义指明几个点

    • RMI是Java用于调用远程方法的API ——①属于Java  ②指的是一个API,不是协议或者其他什么东西
    • 相当于面向对象版的RPC —— RPC是远程过程调用(面向过程)
    • 支持直接传输可序列化的Java类 ——①传输的类是方法调用需要的参数和返回值,而不是实现类,实现类的方法在服务器执行。
    • 支持分布式垃圾回收(暂未涉猎)

    远程调用

      远程调用并不是加载远程的类到本地执行,而是通过传递方法参数到服务器,让服务器执行相应的方法并返回结果给客户端。

    网络协议与IO

      RMI所指的远程调用,说的其实是从一个JVM的对象调用另一个JVM环境下对象方法的过程。两个JVM可以在不同的主机上,也可以在同一台主机上。如果在不同主机上,则方法调用必然需要网络传输,网络传输则必然与Socket通信以及相关的通信协议挂钩,RMI用的底层协议是JRMIP。值得一提的是,使用RMI这个API的好处就是,用户不需要实现底层的网络通信与IO,或者说网络传输对用户来说是透明的。

    远程接口

      客户端和服务端都有的接口,只不过接口的实现类在服务端。

    RMI的工作原理

      

      值得一提的是,我在学习RMI的时候,故我根据理解画了这张图。书上讲到需要用rmic指令生成stub和skeleton。但是实际上,Java后面已经废除了这种方式,skeleton被认为不再需要,但是服务器仍然有一些东西负责skeleton的行为(谁负责,暂不清楚,尚未了解底层实现)。而stub可以动态生成。所以用这张图理解RMI还是没问题的。

    RMI远程服务的实现

    相关概念

    Remote

      java.rmi.server包下的定义的接口,远程接口必须继承与RMI的Remote接口,表明其远程接口的身份。

    RMI registry

      RMI的注册表服务,服务器需要将对应的服务注册到注册表上,此操操作将会绑定对应服务的stub(存根)??突Ф嘶岣莘衿鞯腎P地址找到服务器,然后在服务器的注册表上找对应的存根。

    UnicastRemoteObject

       远程接口的实现类必须继承此类,以用于生成与底层JRMP协议相关的通信对象,以及用于与通信对象连接的stub(存根)。

    服务端实现步骤

      1. 定义远程接口

        定义一个接口,继承于Remote接口。注意,定义的方法需要抛出RemoteException。因为网络和I/O是不安全的,必须让客户意识到这点,做相应的异常处理准备。

      2. 定义远程接口实现

        定义一个类实现上述接口,并继承UnicastRemoteObject??稍诖死?,或其他类中的main方法中,注册服务到注册表表。

        Naming.rebind("serviceName", service);   

      3. 启动RMI registry注册表服务

        利用命令行启动。启动命令所在的目录必须能够访问到你的类。最好在实现类目录启动。

        %rmiregistry           

      4. 开启远程服务(注册服务到注册表)

        执行,带有注册操作的类。

    客户端实现步骤

      1. 定义远程接口

        与服务端的接口相同,直接拷贝过来即可。

      2. 定义访问远程接口的类

        客户端需要定义一个类,用于连接到服务端的注册表,根据服务的相关信息查找并获取stub(存根)。

        Naming.lookup("rmi://ip:port/serviceName");   

       3. 根据stub访问远程接口方法。

    RMI样例代码

    文件图

     

    注:在单机环境下模拟,客户端服务端在不同的文件夹。 

    服务端

    MyRemote.java

    import java.rmi.*;
    
    public interface MyRemote extends Remote {
        public String sayHello() throws RemoteException;
    }
    View Code

    MyRemoteImpl.java

    import java.rmi.*;
    import java.rmi.server.*;
    
    public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
        //实现远程方法
        public String sayHello() {
            return "Server says, 'Hey'";
        }
    
        public MyRemoteImpl() throws RemoteException {
    
        }
    
        //主方法,注册服务到注册表
        public static void main(String[] args) {
            try {
                //创建远程对象
                MyRemote service = new MyRemoteImpl();
                //绑定到注册表
                //rebind方法会覆盖同名方法,相当于先unbind再bind.
                Naming.rebind("RemoteHello", service);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    View Code

    启动RMI Registry注册表服务,注意,此命令没有任何响应,就是开启成功了,不要关闭此弹窗

    启动服务,开启另一个控制台,运行主程序。此主程序同样没有任何输出。

    客户端

    MyRemote同上

    MyRemoteClient.java

    import java.rmi.*;
    
    public class MyRemoteClient {
        public static void main(String[] args) {
            new MyRemoteClient().go();
        }
    
        public void go() {
            try {
                //查找对应服务,并获取到存根
                MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/RemoteHello");
                //利用存根调用接口方法
                String s = service.sayHello();
                //输出返回值
                System.out.println(s);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    View Code

    启动客户端,开启另一个控制台,启动客户端主程序

     为什么远程接口可直接调用Stub

      远程接口能直接调用stub,那很明显,stub就是远程接口的实现类。前面我们提到了,用rmic命令工具生生成stub的方式已经被废除了。stub可以动态生成。但是使用rmic命令工具还是可以生成_stub的class文件。虽然有相关的警告。

    我们可以用反编译工具,来查看其源码。我使用的是jd-gui。

    即,stub确实就是远程接口的实现类。注意,只是语法上实现,真正的实现在服务端。stub算是一个代理,让客户端可以像操作实现类那样操作stub,好像实现类就在本地一样。

     

    posted @ 2018-11-15 10:12 猫毛·波拿巴 阅读(...) 评论(...) 编辑 收藏
  • 豫园商城升级改造:这些楼顶可见最好的风景--旅游频道 2019-05-14
  • 头条 —频道 春城壹网 七彩云南 一网天下 2019-05-14
  • 人为某种意识而奋斗是幸福的,获得成绩或成就更幸福。 2019-05-10
  • 【专题】省违反中央八项规定精神和“四风”问题线索举报平台 2019-05-09
  • 确定这是热身赛?吴前拼到大腿抽筋 拆绷带继续干 2019-05-09
  • 应对排放新规 大众德国工厂计划短暂停产 2019-04-26
  • 一师一团土地确权登记颁证工作全面展开 2019-04-26
  • 一语惊坛(5月31日):“我们不一样”,中国向世界许下一个承诺。 2019-04-22
  • 俄罗斯世界杯F组:球迷风采 2019-04-10
  • 5月份国民经济数据发布:中国经济持续稳中向好 2019-04-10
  • 贵州宣讲十九大:干部争当宣讲员 群众心窝暖洋洋 2019-03-25
  • 别空谈,说说看,这个“简单的逻辑关系”是什么关系? 2019-03-25
  • 快过闪电,MIUI 10与MIUI 9速度对比 2019-03-21
  • 泽州去年“免费教育”资金达5211万元 2019-03-19
  • 看你这么可怜,再提示你一下:你重孙算1,父母为2,父母的父母为4,父母的父母的父母为8…… 2019-03-19
  • 超级大乐透走势图表彩票2元网 快乐12开奖 网易彩票预测 五分彩彩票怎么扫雷最准 黑金团队快乐8下载 贵州福彩 生肖时时彩 生肖时时彩的模拟 开乐彩54期 安徽时时彩 澳洲幸运10开奖直播现场 彩巴巴彩票官网 北京赛车pk拾开奖直播视频 广东彩票开奖时时彩 pk10开奖记录皇家 3d试机号麦久网 北京pk10七码全年可用