zoukankan      html  css  js  c++  java
  • java rmi远程方法调用实例

    RMI的概念

      RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机上的对象可以调用另外一台计算机上的对象来获取远程数据。RMI是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。在过去,TCP/IP套接字通讯是远程通讯的主要手段,但此开发方式没有使用面向对象的方式实现开发,在开发一个如此的通讯机制时往往令程序员感觉到乏味,对此RPC(Remote Procedure Call)应运而生,它使程序员更容易地调用远程程序,但在面对复杂的信息传讯时,RPC依然未能很好的支持,而且RPC未能做到面向对象调用的开发模式。针对RPC服务遗留的问题,RMI出现在世人面前,它被设计成一种面向对象的通讯方式,允许程序员使用远程对象来实现通信,并且支持多线程的服务,这是一次远程通讯的革命,为远程通信开辟新的里程碑。

      Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。

    RMI的开发步骤

    1. 先创建远程接口及声明远程方法,注意这是实现双方通讯的接口,需要继承Remote
    2. 开发一个类来实现远程接口及远程方法,值得注意的是实现类需要继承UnicastRemoteObject
    3. 通过javac命令编译文件,通过java -server 命令注册服务,启动远程对象
    4. 最后客户端查找远程对象,并调用远程方法

    实例源码:

    首先为服务建立一个Model层,注意因为此对象需要现实进行远程传输,所以必须继承Serializable

    package com.blankjor.rmi;
    
    import java.io.Serializable;
    
    /**
     * @desc 传输持久层话数据对象,必须实现Serializable接口
     * @author Blankjor
     * @date 2017年5月30日 下午3:28:45
     */
    public class EntityData implements Serializable {
        private static final long serialVersionUID = 1L;
        private int id;
        private String name;
        private String tel;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getTel() {
            return tel;
        }
    
        public void setTel(String tel) {
            this.tel = tel;
        }
    
    }

    创建远程接口MyRemote,注意远程接口必须要继承Remote

    package com.blankjor.rmi;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    /**
     * @desc 远程接口,实现Remote
     * @author Blankjor
     * @date 2017年5月30日 下午2:49:05
     */
    public interface MyRemote extends Remote {
        EntityData sayHello() throws RemoteException;
    
    }

    建立MyRemoteImpl实现远程接口MyRemote,注意此为远程对象实现类,需要继承UnicastRemoteObject,UnicastRemoteObject实现了需要的远程接口

    package com.blankjor.rmi;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    /**
     * @desc 接口实现,为了完成一些远程的功能,借助UnicastRemoteObject,自动实现
     * @author Blankjor
     * @date 2017年5月30日 下午2:50:39
     */
    public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
    
        /**
         * 必须实现,为了抛出 RemoteException
         * 
         * @throws RemoteException
         */
        protected MyRemoteImpl() throws RemoteException {
        }
    
        @Override
        public EntityData sayHello() throws RemoteException {
            EntityData ed = new EntityData();
            ed.setId(1);
            ed.setName("lyc");
            ed.setTel("110");
            return ed;
        }
    
    }

    建立远程服务端,并开启后进行注册

    package com.blankjor.rmi;
    
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    
    /**
     * @desc 注册远程服务服务端
     * @author Blankjor
     * @date 2017年5月30日 下午2:54:26
     */
    public class MyRemoteServer {
        public static void main(String[] args) {
            try {
                System.out.println("远程服务正在启动,等待调用...");
                // 实例化远程服务对象
                MyRemote remote = new MyRemoteImpl();
                // 进行注册绑定
                LocateRegistry.createRegistry(1234);
                Naming.rebind("rmi://localhost:1234/RemoteHello", remote);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    运行后结果:

    客户端进行远程服务的访问,调用

    package com.blankjor.rmi;
    
    import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.NotBoundException;
    import java.rmi.RemoteException;
    
    /**
     * @desc 调用远程服务的客户端
     * @author Blankjor
     * @date 2017年5月30日 下午3:00:02
     */
    public class MyRemoteClient {
        public static void main(String[] args) {
            try {
                // 寻找远程服务
                MyRemote service = (MyRemote) Naming.lookup("rmi://localhost:1234/RemoteHello");
                // 调用远程服务方法
                EntityData ed = service.sayHello();
                System.out.println("Welcome " + ed.getName());
            } catch (MalformedURLException | RemoteException | NotBoundException e) {
                e.printStackTrace();
            }
        }
    }

     运行后结果:

    总结:
      从上面的过程来看,RMI对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。
    这也是RMI的局限性之一。这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。
      RMI的局限性之二是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现。

     参考:http://www.cnblogs.com/leslies2/archive/2011/05/20/2051844.html

        http://lavasoft.blog.51cto.com/62575/91679/

  • 相关阅读:
    docker stats
    Appium 环境搭建
    docker 进入容器
    Mac下Mysql启动异常["ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)"]
    python 虚拟环境--virtualenv
    visjs 绘图 图标 动态添加数据
    js 滑块登录验证
    js iframe 最顶层显示
    转化为数组
    videojs双击全屏幕观看,videojs动态加载视频
  • 原文地址:https://www.cnblogs.com/KongkOngL/p/6920558.html
Copyright © 2011-2022 走看看