Java的RMI远程方法调用实现和应用

最近在学习Dubbo,RMI是很重要的底层机制,RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机(即JVM虚拟机)上的对象可以调用另外一台计算机上的对象来获取远程数据。

RMI的实现对建立分布式Java应用程序至关重要,是Java体系非常重要的底层技术。

1.RMI的概念和原理

RMI思路是在客户端安装一个代理(proxy),代理是位于客户端虚拟机中的一个对象,对于客户端对象,看起来就像访问的远程对象一样,客户端代理会使用网络协议与服务器进行通信。
同样的服务端也会有一个代理对象来进行通信的繁琐工作。

在RMI中,客户端的代理对象被称为存根(Stub),存根位于客户端机器上,它知道如何通过网络与服务器联系。存根会将远程方法所需的参数打包成一组字节。对参数编码的过程被称为参数编组(parameter marshalling),参数编组的目的是将参数转换成适合在虚拟机之间进行传递的形式。在RMI协议中,对象时使用序列化机制进行编码的。

总的来说,客户端的存根方法构造了一个信息块,它由以下几部分组成
被使用的远程对象的标识符;
被调用的方法的描述;
编组后的参数;

然后,存根将此信息发送给服务器。在服务器的一端,接收器对象执行以下动作:
定位要调用的远程对象;
调用所需的方法,并传递客户端提供的参数;
捕获返回值或调用产生的异常;
将返回值编组,打包送回给客户端存根;
客户端存根对来自服务器端的返回值或异常进行反编组,其结果就成为了调用存根返回值。

2.RMI体系结构

桩/框架(Stub/Skeleton)层:客户端的桩和服务器端的框架;
远程引用(remote reference)层:处理远程引用行为
传送层(transport):连接的建立和管理,以及远程对象的跟踪

3.RMI与代理模式

RMI的实现是典型的代理模式思想。

(1)代理模式的UML图

代理模式为其他对象提供一种代理以控制对这个对象的访问,把调用者与被调用者分离开,由代理负责传递信息来完成调用。
比如你想买美版Iphone6s,朋友出国,帮你海淘带回,整个过程就是代理模式,朋友作为代理,代你完成你想进行的操作。

代理模式能将代理对象与真正被调用的对象分离,在一定程度上降低了系统的耦合度;
在客户端和目标对象之间起到一个中介作用,这样可以起到保护目标对象的作用,代理对象也可以对目标对象调用之前进行其他操作。
代理模式在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢;同时也增加了系统的复杂度。

(2)代理模式在RMI这种的体现

远程代理的内部机制是这样的:

下面的RMI实例,其实就是一个代理模式的应用。

4.RMI的简单实例

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

(1)服务端远程接口
创建远程接口SearchService,接口必须继承Remote类,每一个定义方法都要抛出RemoteException异常

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface SearchService extends Remote {
    public User findUser(String id) throws RemoteException;;
}

(2)建立SearchServiceImpl实现远程接口,注意此为远程对象实现类,需要继承UnicastRemoteObject

import java.rmi.RemoteException;
public class SearchServiceImpl implements SearchService{

    /**
     * 抛出RemoteException
     * @throws RemoteException
     */
    public SearchServiceImpl() throws RemoteException {
        super();
        }

    @Override
    public User findUser(String id) throws RemoteException {
        /**
         * 模拟查找返回数据
         */
        User user=new User(id,"Tom","18岁");
        return user;
    }

}

(3)为服务建立一个Model层,此对象需要远程传输,所以必须实现implements Serializable序列化接口,也就是可以在client和server端进行传输的可序列化对象
新建User类,用于数据传输:

public class User implements Serializable{

    private static final long serialVersionUID = 1L;

    private String id;
    private String name;
    private String age;

    public User(String id,String name,String age){
        this.id=id;
        this.name=name;
        this.age=age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String toString(){
        StringBuffer sb=new StringBuffer();
        sb.append("~用户id-"+id);
        sb.append("~用户姓名-"+id);
        sb.append("~用户年龄-"+id);
        return sb.toString();
    }

}

(4)建立服务器端,在服务器端注册RMI通讯端口与通讯路径

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

/**
 * @author BingYue
 */
public class Process {

    public static void main(String[] args){

        try {
            SearchService searchService=new SearchServiceImpl();
            //注册通信端口
            Registry registry=LocateRegistry.createRegistry(5678);
            //注册通讯路径
            Naming.rebind("rmi://127.0.0.1:5678/searchService", searchService);
            System.out.println("Service Start!");

        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

}

(5)创建客户端,导入上面的实体类和接口,通过Naming.lookup()的方式调用
如果使用IDE,就可以新建一个项目,Client代码如下:

import java.rmi.Naming;

/**
 * @author BingYue
 */
public class Client {

    public static void main(String[] args){
        try {
            //调用远程对象,注意RMI路径与接口必须与服务器配置一致
            SearchService searchService=(SearchService)Naming.lookup("rmi://127.0.0.1:5678/searchService");
            User user=searchService.findUser("100");
            System.out.println(user.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(6)分别运行服务端和客户端,获得远程调用结果

(1)Remote接口:是一个不定义方法的标记接口

Public interface Remote{

}

原文地址:https://www.cnblogs.com/jack-Star/p/8277822.html

时间: 2024-08-06 09:51:08

Java的RMI远程方法调用实现和应用的相关文章

Java之RMI(远程方法调用)

RMI(Remote Method Invocation)中文名称是远程方法调用,可用于分布式计算. 这里就不去详细介绍RMI了,本Blog主要讲叙RMI实战和有哪些需要注意的地方,如果想要查看详细介绍请查看:百度百科RMI RMI分为服务端和客户端 服务端: 创建服务端: LocateRegistry.createRegistry(端口); Naming.rebind("rmi://IP地址:端口/RMI服务名称",RMI服务对象);//rebind也可以用bind替代 示例: Lo

Java RMI(远程方法调用) 实例与分析 (转)

目的: 通过本文,可以加深对Java RMI的理解,知道它的工作原理,怎么使用等. 也为了加深我自己的理解,故整理成文.不足之处,还望指出. 概念解释: RMI(RemoteMethodInvocation):远程方法调用,顾名思义,通过远程的方式调用非本地对象的方法并返回结果.使用远程调用通常解决本地计算瓶颈问题,例如分布式记算,最近很火的阿尔法狗人机大战,据说运算使用上千个CPU. JRMP(java remote method protocol):java远程方法协议,这是完成java到j

Java之——RMI远程过程调用(插曲)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45970641 一.定义          Java RMI:Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远程服务器上的对象.远程方法调用特性使Java编程人员能够在网络环境中分布操作.RMI全部的宗旨就是尽可能简化远程接口对象的

JAVA RMI远程方法调用简单实例[转]

RMI的概念 RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制.使用这种机制,某一台计算机上的对象可以调用另外 一台计算机上的对象来获取远程数据.RMI是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径.在过去,TCP/IP套接字通讯是远程通讯的主要手段,但此开发方式没有使用面向对 象的方式实现开发,在开发一个如此的通讯机制时往往令程序员感觉到乏味,对此RPC(Remote

Java中RMI远程调用demo

Java远程方法调用,即Java RMI(Java Remote Method Invocation),一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远程服务器上的对象.远程方法调用特性使Java编程人员能够在网络环境中分布操作.RMI全部的宗旨就是尽可能简化远程接口对象的使用. Java RMI极大地依赖于接口.在需要创建一个远程对象的时候,程序员通过传递一个接口来隐藏底层的实现细节.客户端得到的远程对象句柄正好与本地的根代码连接,由后者负责透过网络通信.这样一来,

RMI远程方法调用技术

RMI是J2EE技术规范之一,英文全称Remote Method Invocation(即远程方法调用).远程方法调用是一种同一计算机不同Java研发软件系统之间或不同计算机不同Java研发软件系统之间通过调用对方远程方法启动对方进程进而实现交互的一种机制,这种机制为开发分布式应用程序带来了极大的方便. RMI技术的应用通常包括在两个独立的应用程序中:服务端应用程序和客户端应用程序. 服务端应用程序: RMI典型的服务端代码将创建多个远程对象,使这些远程对象能够被引用,然后等待客户端调用这些远程

关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的一些总结-1

原文地址:https://www.anquanke.com/post/id/194384#h3-3 1.java rmi 关于rmi客户端和服务端通信的过程,java的方法都实现在rmi服务端,客户端实际上是通过访问rmi注册表拿到stub,然后再通过它调用服务端方法,那么调用方法时要传递参数,参数可以为一般类型,也可以为引用类型,那么如果为引用类型,就能够利用服务端已经有的gaget chain来打server,因为参数实际上是序列化传输的,那么数据到达服务端后必定会经过反序列化. 客户端:

java RMI入门指南

感觉这篇文章不错,直接转了 RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体如今它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方式之中的一个.事实上它能够被看作是RPC的Java版本号.可是传统RPC并不能非常好地应用于分布式对象系统.而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信.实现远程对象之间的无缝远程调用. RMI眼下使用Java远程消息交换协议JRMP

对JAVA RMI的认识

RMI的定义 RPC (Remote Procedure Call):远程方法调用,用于一个进程调用另一个进程中的过程,从而提供了过程的分布能力. RMI(Remote Method Invocation):远程方法调用,即在RPC的基础上有向前迈进了一步,提供分布式对象间的通讯.允许运行在一个java 虚拟机的对象调用运行在另一个java虚拟机上对象的方法.这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中. RMI的全称宗旨就是尽量简化远程接口对象的调用.