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是完全透明的

  • 相关阅读:
    Tina系统的安装
    检查有无相机的权限
    BarEasy打印小程序_CS
    js的websocket
    生成GUID
    读取excel数据到数据库里
    字符串trim
    使用 runOnUiThread在线程内更新UI
    PdfDocument生成PDF,总是产生空文件
    打印36进制的条码序列号
  • 原文地址:https://www.cnblogs.com/wenruo/p/6559789.html
Copyright © 2011-2022 走看看