zoukankan      html  css  js  c++  java
  • Java RMI 概观

    RMI是Java的一组拥护开发分布式应用程序的API。

    RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol)。

    简单地说,这样使原先的程序在同一操作系统的方法调用,变成了不同操作系统之间程序的方法调用,由于J2EE是分布式程序平台,它以RMI机制实现程序组件在不同操作系统之间的通信。

    RMI的好处在于你不必亲自写网络或I/O代码。

    客户程序调用远程方法(即真正服务器所在)就和在运行在客户自己本地JVM上对对象进行正常方法调用一样。

    RMI将客户辅助对象成为stub(桩),服务辅助对象称为skeleton(骨架)

    五个步骤:

    1.制作远程接口

    远程接口定义出可以让客户端远程调用的方法。客户端将用它作为服务的类类型。Stub和实际的服务都实现此接口。

    Remote是一个“记号”接口,所以Remote不具有方法。

    所有声明的方法都会抛出RemoteException。客户会调用实现远程接口的Stub上的方法,而Stub底层用到了网络和I/O,所以各种坏事请都可能会发生。。。

    确定变量和返回值都是属于原语(primitive)类型或者可序列化(Serializable)类型。因为要在网络中传输,所以要序列化。

    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    // 远程接口
    public interface MyRemote extends Remote {
        // 类的返回值  必须是原语类型  或者  可序列化类型
        public String sayHello() throws RemoteException;
    }

    2.制作远程的实现

    一个做实际工作的类。

    首先要实现MyRemote接口。

    为了成为远程服务对象,需要某些“远程的”功能,最简单的方式是扩展java.rmi.server.UnicastRemoteObject,让超类帮你做这些事情。

    由于超类的构造器会抛出一个异常,所以该类也必须有一个构造器。

    public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
        protected MyRemoteImpl() throws RemoteException {
        }
    
        @Override
        public String sayHello() throws RemoteException {
            return "Server says, 'hey'";
        }
    }

    3.利用rmic产生的stub和skeleton

    客户和服务的辅助类,不需要自己创建。

    我使用Eclipse创建的工程,在工程目录的bin目录下,执行rmic 包名.文件名 

    注意,文件名不加.class

    然后会发现xxxin包下会产生一个MyRemoteImpl_Stub.class文件。

    如警告处所说,没有骨架生成,也就是没有名为MyRemoteImpl_Skel.class的文件。

    4.启动RMI register(rmiregistry)

    在安装JDK的目录的bin目录下,找到了rmiregistry.exe,但是……不知道怎么用……囧……一直报错,然后放弃了在命令行开启rmiregistry

    直接在代码里通过LocateRegistry.createRegistry(12312);创建rmirgistry服务,同时指定端口号。

    先产生远程对象,然后通过Naming.rebind()将远程对象绑定到rmiregistry

    Naming 类提供在对象注册表中存储和获得远程对远程对象引用的方法 

    该名称是使用以下形式的 URL 格式(没有 scheme 组件)的 java.lang.String: 

    host:port/name 

    host:注册表所在的主机(远程或本地),省略则默认为本地主机 

    port:是注册表接受调用的端口号,省略则默认为1099,RMI注册表registry使用的著名端口 

    name:是未经注册表解释的简单字符串 

    import java.net.InetAddress;
    import java.rmi.Naming;
    import java.rmi.registry.LocateRegistry;
    
    public class MyRemoteServer {
        public static void main(String[] args) {
            try {
                // System.out.println(InetAddress.getLocalHost()); //192.168.61.130
                LocateRegistry.createRegistry(12345);
                MyRemote service = new MyRemoteImpl();
                Naming.rebind("rmi://192.168.61.130:12345/RemoteHello", service);
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    5.开始远程服务

    客户端通过Naming.lookup(注册时使用的名字)获得服务。

    import java.rmi.Naming;
    
    public class MyRemoteClient {
        public static void main(String[] args) {
            new MyRemoteClient().go();
        }
        
        public void go() {
            try {
                MyRemote service = (MyRemote) Naming.lookup("rmi://192.168.61.130:12345/RemoteHello");
                String s = service.sayHello();
                System.out.println(s);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    RMI远程调用步骤:

    1. 客户对象调用客户端辅助对象上的方法
    2. 客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象
    3. 服务端辅助对象将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
    4. 调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象
    5. 服务端辅助对象将结果打包,发送给客户端辅助对象
    6. 客户端辅助对象将返回值解包,返回给客户对象
    7. 客户对象获得返回值

    对于客户对象来说,步骤2-6是完全透明的

  • 相关阅读:
    LeetCode 123. Best Time to Buy and Sell Stock III (stock problem)
    精帖转载(关于stock problem)
    LeetCode 122. Best Time to Buy and Sell Stock II (stock problem)
    LeetCode 121. Best Time to Buy and Sell Stock (stock problem)
    LeetCode 120. Triangle
    基于docker 搭建Elasticsearch5.6.4 分布式集群
    从零开始构建一个centos+jdk7+tomcat7的docker镜像文件
    Harbor实现容器镜像仓库的管理和运维
    docker中制作自己的JDK+tomcat镜像
    docker镜像制作---jdk7+tomcat7基础镜像
  • 原文地址:https://www.cnblogs.com/wenruo/p/6559789.html
Copyright © 2011-2022 走看看