RMI基础篇
远程方法调用(Remote Method Invocation,RMI)从JDK1.1就已经实现,它大大增强了Java开发分布式应用的能力。
RMI可以实现通过网络完成不同JVM间的通信,不仅可以传递基本的数据类型,也可以传递对象。
RMI是JVM间的通信,如果服务器或客户端不是Java语言开发的,可以考虑web service或者corba。
RMI可以实现调用的透明性及安全性,客户端本身不关心功能是怎么实现的,只需要调用服务器端代码并关心结果即可。功能只限制于服务器端,客户端无法任意进行操作,也提供了安全性。
RMI实际应用的场景为:处于安全性及性能的考虑,将某些操作的具体实现放在了服务器端。客户端想进行这些操作就需要使用RMI,去调用另一个JVM(经常是不同的PC上)中的方法并得到希望的结果。

RMI利用JNDI在服务器端注册客户端需要调用的类。具体的调用是存根和骨架之间完成的,可以看做是客户端和服务器端的代理。
下面是一个RMI的简单的例子,各个类的作用都有说明。
IHello定义了服务器和客户端间通信的接口,客户端只要调用IHello中的方法即可。
IHello需要继承Remote接口,所有方法都要抛出RemoteException,否则编译不过。
/**
* 定义一个远程接口,必须继承Remote接口,其中需要远程调用的方法必须抛出RemoteException异常
*/
public interface IHello extends Remote { public User user = new User();
public User getUser() throws RemoteException;;
public void setUser(User user) throws RemoteException;;
/**
* 简单的返回“Hello World!"字样
*/
public String helloWorld() throws RemoteException; /**
* 一个简单的业务方法,根据传入的人名返回相应的问候语
*/
public String sayHelloToSomeBody() throws RemoteException;
}
HelloImpl是服务器端实际实现的方法,客户端通过RMI实际调用的就是HelloImpl中的实现。
/**
* 远程的接口的实现
*/
public class HelloImpl extends UnicastRemoteObject implements IHello { private User user;
public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} private static final long serialVersionUID = -8403069777370518716L; /**
* 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,因此这里默认的构造方法必须写,必须声明抛出RemoteException异常
* @throws RemoteException
*/
public HelloImpl() throws RemoteException {
} /**
* 简单的返回“Hello World!"字样
*/
public String helloWorld() throws RemoteException {
return "Hello World!";
} /**
* 一个简单的业务方法,根据传入的人名返回相应的问候语
*/
public String sayHelloToSomeBody() throws RemoteException {
return user.getName() + "!";
}
}
HelloServer完成的是注册功能,将上面实际工作的HelloImpl进行注册,客户端调用时查找已经注册的HelloImpl实例并调用即可。
注册的地址是localhost的8888端口。实际中应用时将localhost改为具体的IP即可。
/**
* 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。
*/
public class HelloServer {
private static User user = new User(); public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} public static void main(String args[]) {
try {
//创建一个远程对象
HelloImpl rhello = new HelloImpl();
//本地主机上的远程对象注册表Registry的实例,并指定端口为8888,这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上
LocateRegistry.createRegistry(8888); //把远程对象注册到RMI注册服务器上,并命名为RHello
//绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的)
Naming.bind("rmi://localhost:8888/RHello",rhello);
// Naming.bind("//localhost:8888/RHello",rhello); System.out.println(">>>>>INFO:远程IHello对象绑定成功!");
} catch (RemoteException e) {
System.out.println("创建远程对象发生异常!");
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.out.println("发生重复绑定对象异常!");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("发生URL畸形异常!");
e.printStackTrace();
}
}
}
HelloClient模拟了客户端的调用,从localhost的8888端口找到注册的HelloImpl实例并调用。
/**
* 客户端测试,在客户端调用远程对象上的远程方法,并返回结果。
*/
public class HelloClient {
public static void main(String args[]){
try {
//在RMI服务注册表中查找名称为RHello的对象,并调用其上的方法
IHello rhello =(IHello) Naming.lookup("rmi://localhost:8888/RHello");
System.out.println(rhello.helloWorld());
User user = new User();
user.setName("inso");
rhello.setUser(user);
System.out.println(rhello.sayHelloToSomeBody());
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
User用于客户端调用服务器端代码时传递的参数,说明RMI支持传递对象,需要实现Serializable接口。
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = -4631891643752276172L;
private String name;
public String getName() {
return "user's name is " + name;
}
public void setName(String name) {
this.name = name;
}
}
先启动HelloServer注册实例,再启动HelloClient进行调用即可看到结果。
还可以将IHello.java,HelloClient.java,User.java拷贝到另外的机器上,模拟客户端实现真正的分布式测试。将服务器端和客户端的localhost改为具体的IP即可。
RMI基础篇的更多相关文章
- 小白入门Docker基础篇
docker是什么 百科上的解释是这样的: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化 ...
- 小白学Docker之基础篇
系列文章: 小白学Docker之基础篇 小白学Docker之Compose 小白学Docker之Swarm PS: 以下是个人作为新手小白学习docker的笔记总结 1. docker是什么 百科上的 ...
- Docker之基础篇
小白学Docker之基础篇 系列文章: 小白学Docker之基础篇 小白学Docker之Compose 小白学Docker之Swarm PS: 以下是个人作为新手小白学习docker的笔记总结 1 ...
- 深入浅出微服务框架dubbo(一):基础篇
一.基础篇 1.1 开篇说明 dubbo是一个分布式服务框架,致力于提供高性能透明化RPC远程调用方案,提供SOA服务治理解决方案.本文旨在将对dubbo的使用和学习总结起来,深入源码探究原理,以备今 ...
- docker+k8s基础篇二
Docker+K8s基础篇(二) docker的资源控制 A:docker的资源限制 Kubernetes的基础篇 A:DevOps的介绍 B:Kubernetes的架构概述 C:Kubernetes ...
- docker+k8s基础篇一
Docker+K8s基础篇(一) docker的介绍 A:为什么是docker B:k8s介绍 docker的使用 A:docker的安装 B:docker的常用命令 C:docker容器的启动和操作 ...
- C#多线程之基础篇3
在上一篇C#多线程之基础篇2中,我们主要讲述了确定线程的状态.线程优先级.前台线程和后台线程以及向线程传递参数的知识,在这一篇中我们将讲述如何使用C#的lock关键字锁定线程.使用Monitor锁定线 ...
- 一步步学习javascript基础篇(0):开篇索引
索引: 一步步学习javascript基础篇(1):基本概念 一步步学习javascript基础篇(2):作用域和作用域链 一步步学习javascript基础篇(3):Object.Function等 ...
- 2000条你应知的WPF小姿势 基础篇<15-21>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师,对C#和WPF有着极深的热情.最为出色的是他维护了两个博客:2,000Things You Should Know ...
随机推荐
- BZOJ1258: [CQOI2007]三角形tri
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1258 如果最后一位是4,那就改成123就好了. 然后最后一位不是4的话,至多三个答案,然后可以 ...
- BZOJ1078: [SCOI2008]斜堆
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1078 每一次进入的点一定是一个极左节点,然后将它所处在的整棵树左右翻转.加上一些情况的处理. ...
- oracle ebs form开发总结
item的布局千万不要去乱动,只要调好长宽和y轴的坐标就好了.form内部集成了很多代码对布局进行动态的调整,而且有一些代码的长宽什么的还是写死了的,我们一动,form可能就识别不了了,然后就显示出来 ...
- c语言中标识符的作用域
1.代码块作用域(block scope) 位于一对花括号之间的所有语句称为一个代码块,在代码块的开始位置声明的标识符具有代码块作用域,表示它们可以被这个代码中的所有语句访问.函数定义的形式参数在函数 ...
- flume1.8 Channel类型介绍(四)
1. Flume Channel Channels是events在agent上进行的存储库.Source添加events,Sink移除events. 1.1 Memory Channel(内存Chan ...
- [国嵌笔记][005][Linux命令详解]
用户管理类命令 添加用户:useradd name 删除用户:userdel -r name "-r"表示删除对应用户的目录 修改密码:passwd name 切换用户:su - ...
- md5加密以及可逆的加密解密算法
md5加密 package gov.mof.fasp2.gcfr.adjustoffset.adjust; import java.security.MessageDigest; public cla ...
- IIS 发布 dedecms 网站教程
这里只是说明了配置 php 前后 iis 默认网站属性的变化,其实在配置完 php 后系统的环境变 量等也是发生了相应的变化了的, 这里就不一一列举了, 这些只有在你手动完成 php 的配置 之后才能 ...
- DEDE中如何过滤掉Html标签,并且截取字符串长度
在dede标签中只要使用2个函数就可以. [field:body function="cn_substr(Html2text(@me),80)"/] Html2text()函数是去 ...
- [转] 分享一个快的飞起的maven的settings.xml文件
<?xml version="1.0"?> <settings> <localRepository>/home/yizhen/.m2/repos ...