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

然后会发现xxx\bin\包\下会产生一个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远程调用步骤:
- 客户对象调用客户端辅助对象上的方法
- 客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象
- 服务端辅助对象将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
- 调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象
- 服务端辅助对象将结果打包,发送给客户端辅助对象
- 客户端辅助对象将返回值解包,返回给客户对象
- 客户对象获得返回值
对于客户对象来说,步骤2-6是完全透明的
Java RMI 概观的更多相关文章
- Exception thrown by the agent : java.rmi.server.ExportException: Port already in use
今天有个应用一直起不来,感觉配置都对啊,奇了怪了.看日志发现如下: STATUS | wrapper | 2017/01/04 08:09:31 | Launching a JVM...INFO | ...
- Java RMI之HelloWorld篇
Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...
- 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099;
错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099; nested exception is: java ...
- JAVA RMI 实例
下面我将介绍一个完整的实例,让初学者能快速体验RMI的功用. 分为以下四个步骤 1. 创建远程接口及声明远程方法(HelloInterface.java)2. 实现远程接口及远程方法(继承Unicas ...
- JAVA RMI例子
RMI 是java语言的一个RPC框架,本文给出基础例子如下: 1.实现接口: public interface ICalc extends Remote { public int add(int p ...
- java.rmi.NoSuchObjectException: no such object in table
jmx链接的时候,最简单的例子都行不通,郁闷,出现了: 参考:http://reiz6153.blog.163.com/blog/static/401089152009442723208/ 代码: M ...
- 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法
一.问题描述 今天一来公司,在IntelliJ IDEA 中启动Tomcat服务器时就出现了如下图所示的错误:
- Java RMI 介绍和例子以及Spring对RMI支持的实际应用实例
RMI 相关知识 RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网 ...
- Java学习笔记(十六)——Java RMI
[前面的话] 最近过的好舒服,每天过的感觉很充实,一些生活和工作的技巧注意了就会发现,其实生活也是可以过的如此的有滋有味,满足现在的状况,并且感觉很幸福. 学习java RMI的原因是最近在使用dub ...
随机推荐
- EL表达式与标签库
https://blog.csdn.net/panhaigang123/article/details/78428567
- CentOS 特殊变量($0、$1、$2、 $?、 $# 、$@、 $*)
名称 说明 $0 脚本名称 $1-9 脚本执行时的参数1到参数9 $? 脚本的返回值 $# 脚本执行时,输入的参数的个数 $@ 输入的参数的具体内容(将输入的参数作为一个多个对象,即是所有参数的一个列 ...
- idea编辑项目出现【Information:java: javacTask: 源发行版 7 需要目标发行版 1.7】
在编译项目时候出现问题: Information:java: javacTask: 源发行版 7 需要目标发行版 1.7 解决方案:按着图片操作,这几个地方设置的一样就可以了
- 【python深入】装饰器理解及使用
装饰器,其实就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下额外增加功能,装饰器的返回是一个函数对象. 用一个例子来说明一下什么是函数对象: 从这里可以看到,直接在函数后面加bar(),就 ...
- 93. Restore IP Addresses产生所有可能的ip地址
[抄题]: Given a string containing only digits, restore it by returning all possible valid IP address c ...
- css初始
css概念及作用 css即层叠样式表的英文缩写 作用:1 渲染页面 2 页面布局 css语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. 格式: selector{ prope ...
- mybatis电子商务平台b2b2c
技术解决方案 开发语言: java.j2ee 数据库:mysql JDK支持版本: JDK1.6.JDK1.7.JDK1.8版本 核心技术:分布式.云服务.微服务.服务编排等. 核心架构: 使用Spr ...
- java 给任务传递参数
之前https://www.cnblogs.com/kexb/p/10228369.html没有参数,这里介绍参数什么传入 package com.hra.riskprice; import com. ...
- IPv6下网络编程socket, TCP和UDP例子,以及兼容IPV4和IPV6的类
一.TCP socket ipv6与ipv4的区别 服务器端源代码如下: #include <stdio.h> #include <stdlib.h> #include < ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记十三之铭文升级版
铭文一级: 第10章 Spark Streaming整合Kafka spark-submit \--class com.imooc.spark.KafkaReceiverWordCount \--ma ...