Java中间件之RMI及实例介绍 · zijian's blog
RMI介绍
远程方法调用(Remote Method Invocation)
是Sun公司规定的允许在不同的JAVA虚拟机之间进行对象间通信的一种规范。在RMI中,JVM可以位于一个或多个计算机上,其中一个JVM可以调用存储在另一个JVM中的对象方法。这就使得应用程序可以远程调用其他对象方法,从而达到分布式计算的目的,以共享各个系统的资源和处理能力。
除了RMI外,基于JAVA的实现不同JAVA虚拟机上的应用程序之间通信技术主要有两种:套接字
和JAVA消息服务(JMS)
。
使用套接字是实现程序间通信的最为灵活和强大的方式。但是它必须通过应用级协议进行通信,要求应用程序之间使用同样的协议,并且要求设计通信过程中的错误判断等。
JMS
和RMI
的区别在于,采用JMS服务,对象是物理上被异步地从网络的某个JVM上直接移动到另一个JVM上。而RMI对象是绑定在本地JVM上,只有函数参数和返回值是通过网络传送的。
RMI开发应用程序的一般步骤
- 定义远程接口
- 实现这个远程接口
- 生成
stub
(客户代理)和skeleton
(服务器实体) - 编写使用远程对象的客户程序
- 启动注册表并登记远程对象
- 运行服务器和客户程序
Eclipse中RMI环境搭建
- 首先下载Eclipse的RMI开发插件 下载地址:http://www.genady.net/rmi/v20/downloads.html
- 解压缩将net.genady.rmi_2.5.0文件夹下的两个文件拷贝到eclipse安装目录下,覆盖同名的两个文件夹
- 重启eclipse即可在快捷栏看到RMI插件标志
简单实例
定义远程接口
1
2
3
4
5
6
7
8package RMIinterface; import java.rmi.Remote;
import java.rmi.RemoteException; public interface extends Remote{
public String sayHello ()throws RemoteException;
}创建一个远程接口时,必须遵守下列规则:
- 远程接口必须为public
- 远程接口必须继承java.rmi.Remote 除应用程序本身有关异常外,
- 远程接口中的每个方法都必须在自己的 throws中声明java.rmi.RemoteException
- 作为参数或返回值传递的一个远程对象,必须声明为远程接口,不可 声明为实现类。
实现这个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package 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";
} }构建服务器程序
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
35package 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();
} } }构建客户程序
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
27package 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();
}
} }打开cmd窗口,对所在位置的接口进行编译。
右键该项目,打开运行配置窗口,找到
RMI VM Properties
后,对java.security.policy
与java.rmi.server.codebase
进行配置
然后在RMI Application方式下运行服务器程序,在Java Application方式下运行客户程序。
结合XML编程的RMI实例——航班信息查询(通过查询目的地显示到达该目的地的所有航班信息)
编写多个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">航班>
</航班列表>定义远程接口
1
2
3
4
5
6
7
8
9package searchF; import java.rmi.Remote;
import java.rmi.RemoteException; public interface SearchFlight extends Remote{
public void SearchF()throws RemoteException; }实现这个远程接口
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
90package 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;
}
}构建服务器程序
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
29package 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();
}
}
}构建客户程序
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
26package 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();
}
} }以RMI Application方式运行服务器程序,正常运行客户端程序,运行结果如下:
Java中间件之RMI及实例介绍 · zijian's blog的更多相关文章
- java远程调用rmi入门实例
RMI是Java的一组拥护开发分布式应用程序的API.RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol). ...
- 大型网站系统与Java中间件实践
大型网站系统与Java中间件实践(贯通分布式高并发高数据高访问量网站架构与实现之权威著作,九大一线互联网公司CTO联合推荐) 曾宪杰 著 ISBN 978-7-121-22761-5 2014年4 ...
- 淘宝JAVA中间件Diamond详解(2)-原理介绍
淘宝JAVA中间件Diamond详解(二)---原理介绍 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本次为大家带来的是diamond核心原理的介绍,主要包括server ...
- java rmi 入门实例
java rmi 入门实例 (2009-06-16 16:07:55) 转载▼ 标签: java rmi 杂谈 分类: java-基础 java rmi即java远程接口调用,实现了2台虚拟机之 ...
- 《大型网站系统与Java中间件实践》读书笔记
分布式系统的基础知识 阿姆达尔定律 多线程交互模式 互不通信,没有交集,各自执行各自的任务和逻辑 基于共享容器(如队列)协同的多线程模式->生产者-消费者->队列 通过事件协同的多线程模式 ...
- 关于metaspolit中进行JAVA反序列化渗透RMI的原理分析
一.背景: 这里需要对java反序列化有点了解,在这里得推广下自己的博客嘛,虽然写的不好,广告还是要做的.原谅我: 1.java反序列化漏洞原理研习 2.java反序列化漏洞的检测 二.攻击手法简介 ...
- Java开发中RMI和webservice区别和应用领域
Java开发中RMI和webservice区别和应用领域 一.RMI和webservice区别和联系 0. 首先,都是远程调用技术. 1. RMI是在TCP协议上传递可序列化的java对象(使用Str ...
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 | 被围观 25,969 views+ 1.Anno ...
- Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
随机推荐
- 实现迭代器(\_\_next\_\_和\_\_iter\_\_)
目录 实现迭代器(__next__和__iter__) 一.简单示例 二.StopIteration异常版 三.模拟range 四.斐波那契数列 实现迭代器(__next__和__iter__) 一. ...
- Docker添加root用户
0 环境 系统环境:centos7 服务器:阿里云 1 正文 1 进入rabbitmq容器中 docker exec -i -t 563 bin/bash 2 添加用户(用户名和密码) rabbitm ...
- 理解python的可变参数
以 str.format(*args,**kwargs) 为例. "type1:{},{},{},{}_type2:{a},{b},{c},{d}".format('a',2,*[ ...
- rabbitmq安装(linux)遇到 很多坑
1.下载erlang官网地址 http://www.erlang.org/download 挑选合适的版本 然后 建议20.3运行命令 wget http://erlang.org/download/ ...
- 吴裕雄--天生自然 pythonTensorFlow自然语言处理:Attention模型--训练
import tensorflow as tf # 1.参数设置. # 假设输入数据已经转换成了单词编号的格式. SRC_TRAIN_DATA = "F:\\TensorFlowGoogle ...
- apache commons类库的学习
原文地址http://www.tuicool.com/articles/iyEbquE 1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默 ...
- DOM(Document Object Model)
DOM(Document Object Model): 结点的概念:整个文档就是由层次不同的多个节点组成,可以说结点代表了全部内容. 结点类型 1.元素结点 对于元素结点的n ...
- StartDT AI Lab | 视觉智能引擎之算法模型加速
通过StartDT AI Lab专栏之前多篇文章叙述,相信大家已经对计算机视觉技术及人工智能算法在奇点云AIOT战略中的支撑作用有了很好的理解.同样,这种业务牵引,技术覆盖的模式也收获了市场的良好反响 ...
- mysql中datetime时间转字符串(避免java层映射为数字串)
-- in_date datetime NULLDATE_FORMAT(ls.`in_date`,'%Y-%m-%d %T')AS create_time
- hdu5452
http://acm.hdu.edu.cn/showproblem.php?pid=5452 题意:给个图T(图G的最小生成树),然后再给定图G的剩余边,问你从图T中当且割一条边的情况再割图G中不属于 ...