[首页]
[文章]
[教程]
首页
Web开发
Windows开发
编程语言
数据库技术
移动平台
系统服务
微信
设计
布布扣
其他
数据分析
首页
>
其他
> 详细
rmi 工作原理
时间:
2015-09-17 21:27:27
阅读:
198
评论:
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年09月23日 (328)
2021年09月24日 (313)
2021年09月17日 (191)
2021年09月15日 (369)
2021年09月16日 (411)
2021年09月13日 (439)
2021年09月11日 (398)
2021年09月12日 (393)
2021年09月10日 (160)
2021年09月08日 (222)
最新文章
更多>
2021/09/28 scripts
2022-05-27
vue自定义全局指令v-emoji限制input输入表情和特殊字符
2022-05-27
9.26学习总结
2022-05-27
vim操作
2022-05-27
深入理解计算机基础 第三章
2022-05-27
C++ string 作为形参与引用传递(转)
2022-05-27
python 加解密
2022-05-27
JavaScript-对象数组里根据id获取name,对象可能有children属性
2022-05-27
SQL语句——保持现有内容在后面增加内容
2022-05-27
virsh命令文档
2022-05-27
教程昨日排行
更多>
1.
list.reverse()
2.
Django Admin 管理工具
3.
AppML 案例模型
4.
HTML 标签列表(功能排序)
5.
HTML 颜色名
6.
HTML 语言代码
7.
jQuery 事件
8.
jEasyUI 创建分割按钮
9.
jEasyUI 创建复杂布局
10.
jEasyUI 创建简单窗口
友情链接
汇智网
PHP教程
插件网
关于我们
-
联系我们
-
留言反馈
- 联系我们:wmxa8@hotmail.com
© 2014
bubuko.com
版权所有
打开技术之扣,分享程序人生!