RMI介绍

  远程方法调用(Remote Method Invocation)是Sun公司规定的允许在不同的JAVA虚拟机之间进行对象间通信的一种规范。在RMI中,JVM可以位于一个或多个计算机上,其中一个JVM可以调用存储在另一个JVM中的对象方法。这就使得应用程序可以远程调用其他对象方法,从而达到分布式计算的目的,以共享各个系统的资源和处理能力。

  除了RMI外,基于JAVA的实现不同JAVA虚拟机上的应用程序之间通信技术主要有两种:套接字JAVA消息服务(JMS)

  使用套接字是实现程序间通信的最为灵活和强大的方式。但是它必须通过应用级协议进行通信,要求应用程序之间使用同样的协议,并且要求设计通信过程中的错误判断等。

  JMSRMI的区别在于,采用JMS服务,对象是物理上被异步地从网络的某个JVM上直接移动到另一个JVM上。而RMI对象是绑定在本地JVM上,只有函数参数和返回值是通过网络传送的

RMI开发应用程序的一般步骤

  1. 定义远程接口
  2. 实现这个远程接口
  3. 生成stub(客户代理)和skeleton(服务器实体)
  4. 编写使用远程对象的客户程序
  5. 启动注册表并登记远程对象
  6. 运行服务器和客户程序

Eclipse中RMI环境搭建

  1. 首先下载Eclipse的RMI开发插件 下载地址:http://www.genady.net/rmi/v20/downloads.html
  2. 解压缩将net.genady.rmi_2.5.0文件夹下的两个文件拷贝到eclipse安装目录下,覆盖同名的两个文件夹
  3. 重启eclipse即可在快捷栏看到RMI插件标志

简单实例

  1. 定义远程接口

    1
    2
    3
    4
    5
    6
    7
    8
    package RMIinterface;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException; public interface extends Remote{
    public String sayHello ()throws RemoteException;
    }

    创建一个远程接口时,必须遵守下列规则:

    1. 远程接口必须为public
    2. 远程接口必须继承java.rmi.Remote 除应用程序本身有关异常外,
    3. 远程接口中的每个方法都必须在自己的 throws中声明java.rmi.RemoteException
    4. 作为参数或返回值传递的一个远程对象,必须声明为远程接口,不可 声明为实现类。
  2. 实现这个接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package rmiIMP;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject; import RMIinterface.iHello; public class rmiIMP extends UnicastRemoteObject implements { private static final long serialVersionUID = 1L; public rmiIMP() throws RemoteException {
    } public String sayHello() throws RemoteException {
    return "hello zhang";
    } }
  3. 构建服务器程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package rmiServer;
    
    import java.net.MalformedURLException;
    import java.rmi.AlreadyBoundException;
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry; import rmiIMP.rmiIMP;
    import RMIinterface.iHello; public class helloServer { public static void main(String[] args) { try {
    iHello ihello = new rmiIMP();
    LocateRegistry.createRegistry(1099);
    Naming.bind("rmi://localhost:1099/iHello",ihello); } catch (RemoteException e) {
    System.out.println("创建远程对象异常!");
    e.printStackTrace();
    } catch (MalformedURLException e) {
    System.out.println("URL异常!");
    e.printStackTrace();
    } catch (AlreadyBoundException e) {
    System.out.println("绑定异常!");
    e.printStackTrace();
    } } }
  4. 构建客户程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package rmiClient;
    
    import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.NotBoundException;
    import java.rmi.RemoteException; import RMIinterface.iHello; public class helloClient { public static void main(String[] args) {
    try {
    iHello ihello = (iHello) Naming.lookup("rmi://localhost:1099/iHello");
    System.out.println(ihello.sayHello()); } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (RemoteException e) {
    e.printStackTrace();
    } catch (NotBoundException e) {
    e.printStackTrace();
    }
    } }
  5. 打开cmd窗口,对所在位置的接口进行编译。

  6. 右键该项目,打开运行配置窗口,找到RMI VM Properties后,对java.security.policyjava.rmi.server.codebase进行配置

  7. 然后在RMI Application方式下运行服务器程序,在Java Application方式下运行客户程序。

结合XML编程的RMI实例——航班信息查询(通过查询目的地显示到达该目的地的所有航班信息)

  1. 编写多个XML文件,每个XML文件表示一所航空公司。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <?xml version="1.0" encoding="GB2312"?>
    <!DOCTYPE 航班列表 [
    <!ELEMENT 航班列表 (航班)*>
    <!ELEMENT 航班 (编号,始发地,目的地,出发时间,到达时间)>
    <!ELEMENT 编号 (#PCDATA)>
    <!ELEMENT 始发地 (#PCDATA)>
    <!ELEMENT 目的地 (#PCDATA)>
    <!ELEMENT 出发时间 (#PCDATA)>
    <!ELEMENT 达到时间 (#PCDATA)>
    ]>
    <航班列表>
    <航班>
    <编号>101</编号>
    <始发地>武汉</始发地>
    <目的地>北京</目的地>
    <出发时间>2016-05-02 16:30</出发时间>
    <到达时间>2016-05-02 19:25</到达时间>
    </航班>
    <航班>
    <编号>102</编号>
    <始发地>深圳</始发地>
    <目的地>成都</目的地>
    <出发时间>2016-05-03 10:15</出发时间>
    <到达时间>2015-05-03 14:00</到达时间>
    </航班>
    <航班>
    <编号>103</编号>
    <始发地>北京</始发地>
    <目的地>天津</目的地>
    <出发时间>2016-05-02 16:30</出发时间>
    <到达时间>2016-05-02 19:25</到达时间>
    </大专栏  Java中间件之RMI及实例介绍 · zijian's blog"name">航班>
    </航班列表>
  2. 定义远程接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package searchF;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException; public interface SearchFlight extends Remote{
    public void SearchF()throws RemoteException; }
  3. 实现这个远程接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    package searchIMP;
    
    import java.io.File;
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    import java.util.Scanner; import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList; import searchF.SearchFlight; public class searchFIMP extends UnicastRemoteObject implements SearchFlight{ private static final long serialVersionUID = 1L; public searchFIMP() throws RemoteException {
    super();
    } public void SearchF() throws RemoteException {
    try { //获得一个XML文件的解析器
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    //解析XML文件生成DOM文档的接口类,以便访问DOM
    DocumentBuilder builder = factory.newDocumentBuilder();
    System.out.print("请输入您要查询的目的地:");
    Scanner scan = new Scanner(System.in);
    String city = scan.nextLine();
    scan.close();
    int[] temp = new int[3];
    int[] count = new int[3];
    for(int k = 0 ; k < 3; k++){
    String airport = "flight"+ (k+1) +".xml";
    //Document接口描述了对应于整个XML文件的文档树
    Document document = builder.parse(new File(airport));
    //获取“航班”元素的子节点列表
    NodeList nodelist = document.getElementsByTagName("航班");
    temp[k] = nodelist.getLength();
    count[k] = 0;
    for (int i = 0; i < nodelist.getLength(); i++) {
    NodeList nl = nodelist.item(i).getChildNodes();
    if(getFlight(nl, city)) {
    if(k == 0 && count[k] == 0)
    System.out.println("到达该目的地的所有航班信息如下:");
    count[k] ++;
    for (int j = 0; j < nl.getLength(); j++) {
    Node cnode = nl.item(j);
    if (cnode.getNodeType() == Node.ELEMENT_NODE) {
    System.out.println(" -->" + cnode.getNodeName() + ": " + cnode.getTextContent());
    }
    }
    System.out.println();
    }else
    temp[k]--;
    }
    }
    if(temp[0] + temp[1] + temp[2] == 0 )
    System.out.println("没有到达该目的地的航班信息!");
    else{
    int sum = count[0]+count[1]+count[2];
    System.out.println("共有"+ sum + "条航班信息!");
    }
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    } //判断所当前航班的目的地城市是否为所查询城市,若是,则返回true
    public static boolean getFlight(NodeList nodelist, String str) {
    boolean temp = false;
    for (int i = 0; i < nodelist.getLength(); i++) {
    Node node = nodelist.item(i);
    if (node.getNodeType() == Node.ELEMENT_NODE) {
    if (node.getTextContent().equals(str) && node.getNodeName().equals("目的地")) {
    temp = true;
    }
    }
    }
    return temp;
    }
    }
  4. 构建服务器程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    package searchServer;
    
    import java.net.MalformedURLException;
    import java.rmi.AlreadyBoundException;
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    import searchF.SearchFlight;
    import searchIMP.searchFIMP; public class searchFServer { public static void main(String[] args) {
    try {
    searchFIMP imp = new searchFIMP();
    LocateRegistry.createRegistry(1099);
    Naming.bind("rmi://localhost:1099/searchFIMP",imp); } catch (RemoteException e) {
    System.out.println("创建远程对象异常!");
    e.printStackTrace();
    } catch (MalformedURLException e) {
    System.out.println("URL异常!");
    e.printStackTrace();
    } catch (Exception e){
    e.printStackTrace();
    }
    }
    }
  5. 构建客户程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    package searchClient;
    
    import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.NotBoundException;
    import java.rmi.RemoteException;
    import searchF.SearchFlight; public class searchFClient { public static void main(String[] args) {
    try {
    SearchFlight searchF = (SearchFlight) Naming.lookup("rmi://localhost:1099/searchFIMP");
    searchF.SearchF(); } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (RemoteException e) {
    e.printStackTrace();
    } catch (NotBoundException e) {
    e.printStackTrace();
    }
    } }
  6. 以RMI Application方式运行服务器程序,正常运行客户端程序,运行结果如下:

Java中间件之RMI及实例介绍 · zijian's blog的更多相关文章

  1. java远程调用rmi入门实例

    RMI是Java的一组拥护开发分布式应用程序的API.RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol). ...

  2. 大型网站系统与Java中间件实践

    大型网站系统与Java中间件实践(贯通分布式高并发高数据高访问量网站架构与实现之权威著作,九大一线互联网公司CTO联合推荐) 曾宪杰 著   ISBN 978-7-121-22761-5 2014年4 ...

  3. 淘宝JAVA中间件Diamond详解(2)-原理介绍

    淘宝JAVA中间件Diamond详解(二)---原理介绍 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本次为大家带来的是diamond核心原理的介绍,主要包括server ...

  4. java rmi 入门实例

    java rmi 入门实例 (2009-06-16 16:07:55) 转载▼ 标签: java rmi 杂谈 分类: java-基础    java rmi即java远程接口调用,实现了2台虚拟机之 ...

  5. 《大型网站系统与Java中间件实践》读书笔记

    分布式系统的基础知识 阿姆达尔定律 多线程交互模式 互不通信,没有交集,各自执行各自的任务和逻辑 基于共享容器(如队列)协同的多线程模式->生产者-消费者->队列 通过事件协同的多线程模式 ...

  6. 关于metaspolit中进行JAVA反序列化渗透RMI的原理分析

    一.背景: 这里需要对java反序列化有点了解,在这里得推广下自己的博客嘛,虽然写的不好,广告还是要做的.原谅我: 1.java反序列化漏洞原理研习 2.java反序列化漏洞的检测 二.攻击手法简介 ...

  7. Java开发中RMI和webservice区别和应用领域

    Java开发中RMI和webservice区别和应用领域 一.RMI和webservice区别和联系 0. 首先,都是远程调用技术. 1. RMI是在TCP协议上传递可序列化的java对象(使用Str ...

  8. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  9. Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

随机推荐

  1. Pytorch基础——使用 RNN 生成简单序列

    一.介绍 内容 使用 RNN 进行序列预测 今天我们就从一个基本的使用 RNN 生成简单序列的例子中,来窥探神经网络生成符号序列的秘密. 我们首先让神经网络模型学习形如 0^n 1^n 形式的上下文无 ...

  2. intellij debug模式提示 Method breakpoints may dramatically slow down debugging

    之前不小心打了一个断点,然后项目长时间不能启动,保持一个加载的状态,并且提示Method breakpoints may dramatically slow down debugging,百度之后才知 ...

  3. 设置Schema-Registry的配置,以支持Schema变化

    设置Schema-Registry的配置,以支持Schema变化 https://blog.csdn.net/lzufeng/article/details/81566766 curl -X PUT ...

  4. Entity Framework实现属性映射约定

    Entity Framework Code First属性映射约定中“约定”一词,在原文版中为“Convention”,翻译成约定或许有些不好理解,这也是网上比较大多数的翻译,我们就当这是Entity ...

  5. 01 语言基础+高级:1-7 异常与多线程_day05 【异常、线程】

    day05 [异常.线程] 主要内容 异常.线程 教学目标 能够辨别程序中异常和错误的区别 说出异常的分类 说出虚拟机处理异常的方式 列举出常见的三个运行期异常 能够使用try...catch关键字处 ...

  6. Cell theory|Bulk RNA-seq|Cellar heterogeneity|Micromanipulation|Limiting dilution|LCM|FACS|MACS|Droplet|10X genomics|Human cell atlas|Spatially resolved transcriptomes|ST|Slide-seq|SeqFISH|MERFISH

    生物信息学 Cell theory:7个要点 All known living things are made up of one or more cells. All living cells ar ...

  7. Caffe Ubuntu14.04 + CUDA 8 (支持GTX1080 1070等Pascal架构显卡)

    1. 前言 本教程使用的系统是Ubuntu 14.04 LTS 64-bit,使用的CUDA版本为8. 理论上本教程支持Pascal架构显卡,如游戏卡GeForce GTX1070,GTX 1080, ...

  8. 利用GIt命令上传项目到GitHub指定仓库

    1.建立GIt可管理的仓库 cd到本地项目根目录下,执行 git init 命令: git init 2.将项目的所有文件添加到仓库中(注意add后面有一个“ . ”) git add . 3.将上一 ...

  9. [GX/GZOI2019]宝牌一大堆(DP)

    出这种麻将题有意思吗? 乍看很难实则很水,就是麻将式DP,想必大家很熟悉了吧.首先把“国士无双”和“七对子”两种牌型判掉,然后观察牌胡的形式,发现每多一张牌实际上就是把1个面子变成1个杠子,然后可以直 ...

  10. An internal error occurred during: "Redeploy".

    原因:项目中JDK使用的版本与现在使用的JDK版本不同所致. 解决方法:右键选择项目>properties>java Build Path>Libraries 查看下面的JRE Sy ...