首页
Web开发
Windows程序
编程语言
数据库
移动开发
系统相关
微信
其他好文
会员
首页
>
其他好文
> 详细
rmi 工作原理
时间:
2015-09-17 21:27:36
阅读:
212
评论:
0
收藏:
0
[点我收藏+]
标签:
rmi 工作原理 (转)
工作
Socket
Java
应用服务器
网络应用
RMI(Remote Method Invocation,远程方法调用)是Java的一组拥护开发分布式应用程序的API。RMI使用Java语言接口定义了远程对象,它集合了Java序 列化和Java远程方法协议(Java Remote Method Protocol)。它大大增强了Java开发分布式应用的能力。简单地说,这样使原先的程序在同一操作系统的方法调用,变成了不同操作系统之间程序的方 法调用。这也就说明,RMI可以实现在不同的JVM之间执行方法的调用。由于J2EE是分布式程序平台,RMI机制实现程序组件在不同操作系统之间的通 信。
下图是RMI的体系结构:
通过RMI的体系结构,已经可以看出RMI的大致工作原理:
服务器端提供服务,服务中要暴露可以调用的远程方法,以接口的形式表现,这样在客户端可以通过服务接口来调用远程方法,实现复杂的业务逻辑。在服 务器端,首先要对接口中提供的方法实现,以便客户端调用能够完成一定的业务逻辑;接着需要生成Skeleton,在Skeleton中真正地实现了对商业 方法的调用,完成了客户请求的调用的过程,将获取到的调用方法的结果通过序列化机制返回给客户端,进行应答。在客户端,通过Stub来接收服务器返回的数 据(对象),即在这里进行了反序列化,也就是读取网络传输的字节流,进而进行重构。在Skeleton和Stub中,都对网络通信进行了处理,例如建立套 接字,建立网络连接,为实际的业务需要做好准备。
可见,客户端并没有真正地执行与服务器端组件进行直接交互。
这里,有个重要的概念,就是Java对象序列化机制。序列化,就是将对象写入流,以便能够在网络上传输对象,它是输出端执行的。反序列化,也就是 在接收端,为了能够获取传输的对象,需要将对象传输而来的字节流进行重构,重新得到完整的该对象。Java对象序列化的过程,是对已有的类的实例进行序列 化,首先要存在一个具体的实例。
下面通过在客户端调用服务器端的方法,实现一个例子,可以很直观地模拟RMI工作,从而进一步深化对RMI工作机制的理解。我使用Oracle JDeveloper 10g开发测试。
开发过程
1、在服务接口中,将客户端可以进行调用的方法暴露给客户端。
ShirdrnService接口中列出了可以调用的方法,ShirdrnService接口如下所示:
Java代码
package org.shirdrn.rmi.server;
import java.io.IOException;
public
interface ShirdrnService {
public String getServerTime()
throws IOException, ClassNotFoundException;
public String getGreetings ()
throws IOException, ClassNotFoundException;
}
2、在服务器端要真正实现服务接口中的这些方法,ShirdrnServiceImpl类实现了ShirdrnService接口中列出的方法。
ShirdrnServiceImpl类的实现如下所示:
Java代码
package org.shirdrn.rmi.server;
import java.io.IOException;
import java.util.Date;
public
class ShirdrnServiceImpl
implements ShirdrnService {
public ShirdrnServiceImpl() {
}
public String getServerTime()
throws IOException, ClassNotFoundException{
Date date =
new Date();
String time = date.toLocaleString();
return time;
}
public String getGreetings()
throws IOException, ClassNotFoundException{
Date date =
new Date();
int hour = date.getHours();
String greetings =
"";
if(hour <
12 && hour >
6){
greetings =
"上午好!";
}
else
if(hour <=
18 && hour >
12){
greetings =
"下午好!";
}
else{
greetings =
"晚上好!";
}
return greetings;
}
}
3、客户端Stub的实现
ShirdrnStub类实现了ShirdrnService接口,它是客户端获取服务结果数据最直接的实现。然而,它并没有与服务器端真正实现服务接口的实现类直接打交道,而是通过网络传输获取到调用方法的执行结果数据。
Java代码
package org.shirdrn.rmi.client;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import org.shirdrn.rmi.server.ShirdrnService;
public
class ShirdrnStub
implements ShirdrnService{
Socket socket;
public ShirdrnStub() {
try {
socket =
new Socket(
"56987b31c0b246d",
8888);
}
catch (UnknownHostException e) {
e.printStackTrace();
System.out.println(
"[信息]创建套接字异常:未知的主机名称。");
}
catch (IOException e) {
e.printStackTrace();
}
}
public String getServerTime()
throws IOException, ClassNotFoundException {
ObjectOutputStream oos =
new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(
"getServerTime");
oos.flush();
ObjectInputStream ois =
new ObjectInputStream(socket.getInputStream());
return (String)ois.readObject();
}
public String getGreetings()
throws IOException, ClassNotFoundException {
ObjectOutputStream oos =
new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(
"getGreetings");
oos.flush();
ObjectInputStream ois =
new ObjectInputStream(socket.getInputStream());
return (String)ois.readObject();
}
}
4、服务器端Skeleton的实现
ShirdrnSkeleton类继承了Thread,因此它可以启动服务器端线程,而且是单线程。在 ShirdrnSkeleton中,真正与提供服务实现的类进行了交互。在建立起连接以后,首先获取到客户端调用的方法,根据客户的选择来直接与服务的实 现交互,执行方法获得执行结果数据,从而将结果数据进行序列化,通过网络传输给客户完成应答过程。
实例化ShirdrnSkeleton类的一个实例后,启动线程,这很像是一个服务器端监听器,监听客户端动作,从而完成服务的请求。
Java代码
package org.shirdrn.rmi.server;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public
class ShirdrnSkeleton
extends Thread {
ShirdrnServiceImpl shirdrnServiceImpl;
public ShirdrnSkeleton(ShirdrnServiceImpl shirdrnServiceImpl) {
this.shirdrnServiceImpl = shirdrnServiceImpl;
}
public
void run() {
try {
ServerSocket serverSocket =
new ServerSocket(
8888);
Socket socket = serverSocket.accept();
while(socket !=
null){
ObjectInputStream ois =
new ObjectInputStream(socket.getInputStream());
String method = (String)ois.readObject();
if(method.equals(
"getServerTime")){
String serverTime = shirdrnServiceImpl.getServerTime();
ObjectOutputStream oos =
new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(serverTime);
oos.flush();
}
if(method.equals(
"getGreetings")){
String greetings = shirdrnServiceImpl.getGreetings();
ObjectOutputStream oos =
new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(greetings);
oos.flush();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public
static
void main(String[] args){
ShirdrnServiceImpl ssi =
new ShirdrnServiceImpl();
ShirdrnSkeleton skeleton =
new ShirdrnSkeleton(ssi);
skeleton.start();
}
}
5、客户端测试程序
通过ShirdrnClient类中的主函数,实现了对服务器端提供的服务接口中的方法进行调用:
Java代码
package org.shirdrn.rmi.client;
import java.io.IOException;
import org.shirdrn.rmi.server.ShirdrnService;
public
class ShirdrnClient {
public ShirdrnClient() {
}
public
static
void main(String[] args)
throws IOException,
ClassNotFoundException {
ShirdrnService stub =
new ShirdrnStub();
System.out.println(
"正在获取服务器时间...");
System.out.println(
"服务器时间 : "+stub.getServerTime());
System.out.println(
"正在获取问候语...");
System.out.println(
"问候语为 : "+stub.getGreetings());
}
}
6、测试过程
心得总结
1、客户端是直接通过实例化一个Stub,因为Stub实现了服务方暴露的接口,所以可以直接通过一个Stub的实例来调用服务方法。但是,这并没有直接调用服务方的服务接口的实现。
2、服务方具有服务接口的真正实现。而真正调用服务接口实现类是在服务器端的Skeleton中,在Skeleton中负责调用真正的服务实现,将执行结果返回给客户端,屏蔽了方法调用的实现细节。
3、客户端Stub和服务器端Skeleton之间建立起网络连接,进行了网络通信,主要就是对执行结果进行传输/接收,Skeleton将结果通过网络传输到客户端,而Stub通过代理接口接收传输而来的结果数据。
rmi 工作原理
标签:
原文地址:http://www.cnblogs.com/fsh1542115262/p/4817441.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年07月29日 (22)
2021年07月28日 (40)
2021年07月27日 (32)
2021年07月26日 (79)
2021年07月23日 (29)
2021年07月22日 (30)
2021年07月21日 (42)
2021年07月20日 (16)
2021年07月19日 (90)
2021年07月16日 (35)
周排行
更多
分布式事务
2021-07-29
OpenStack云平台命令行登录账户
2021-07-29
getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()
2021-07-29
【K8s概念】CSI 卷克隆
2021-07-29
vue3.0使用ant-design-vue进行按需加载原来这么简单
2021-07-29
stack栈
2021-07-29
抽奖动画 - 大转盘抽奖
2021-07-29
PPT写作技巧
2021-07-29
003-核心技术-IO模型-NIO-基于NIO群聊示例
2021-07-29
Bootstrap组件2
2021-07-29
友情链接
兰亭集智
国之画
百度统计
站长统计
阿里云
chrome插件
新版天听网
关于我们
-
联系我们
-
留言反馈
© 2014
mamicode.com
版权所有 联系我们:gaon5@hotmail.com
迷上了代码!