博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java RMI 框架
阅读量:6180 次
发布时间:2019-06-21

本文共 2995 字,大约阅读时间需要 9 分钟。

RMI
(即
Remote Method Invoke 
远程方法调用)。在
Java
中,只要一个类
extends
java.rmi.Remote
接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。
JavaDoc
描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在
远程接口
(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。 
 
注意:extends
Remote
接口的类或者其他接口中的方法若是声明抛出了
RemoteException
异常,则表明该方法可被客户端远程访问调用。 
 
同时,远程对象必须实现
java.rmi.server.UniCastRemoteObject
类,这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以
Socket
的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。 
 
RMI 
框架的基本原理大概如下图,应用了代理模式来封装了本地存根与真实的远程对象进行通信的细节。
下面给出一个简单的RMI 
应用,其中类图如下:其中
IService
接口用于声明服务器端必须提供的服务(即
service()
方法),
ServiceImpl
类是具体的服务实现类,而
Server
类是最终负责注册服务器远程对象,以便在服务器端存在骨架代理对象来对客户端的请求提供处理和响应。
各个类的源代码如下:
IService
接口:
 
import java.rmi.Remote; 
import java.rmi.RemoteException; 
public 
interface IService 
extends Remote { 
  
//声明服务器端必须提供的服务 
  String service(String content) 
throws RemoteException; 
}
ServiceImpl
实现类:
import java.rmi.RemoteException; 
//UnicastRemoteObject用于导出的远程对象和获得与该远程对象通信的存根。 
import java.rmi.server.UnicastRemoteObject; 
public 
class ServiceImpl 
extends UnicastRemoteObject 
implements IService { 
  
private String name; 
  
public ServiceImpl(String name) 
throws RemoteException { 
    
this.name = name; 
  } 
  @Override 
  
public String service(String content) { 
    
return 
"server >> " + content; 
  } 
}
Server
类:
/* 
* Context接口表示一个命名上下文,它由一组名称到对象的绑定组成。 
* 它包含检查和更新这些绑定的一些方法。 
*/
 
import javax.naming.Context; 
/* 
* InitialContext类是执行命名操作的初始上下文。    
* 该初始上下文实现 Context 接口并提供解析名称的起始点。 
*/
 
import javax.naming.InitialContext; 
public 
class Server { 
  
public 
static 
void main(String[] args) { 
    
try { 
      
//实例化实现了IService接口的远程服务ServiceImpl对象 
      IService service02 = 
new ServiceImpl(
"service02"); 
      
//初始化命名空间 
      Context namingContext = 
new InitialContext(); 
      
//将名称绑定到对象,即向命名空间注册已经实例化的远程服务对象 
      namingContext.rebind(
"rmi://localhost/service02", service02); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    System.out.println("服务器向命名表注册了1个远程服务对象!"); 
  } 
}
Client
类:
import javax.naming.Context; 
import javax.naming.InitialContext; 
public 
class Client { 
  
public 
static 
void main(String[] args) { 
    String url = 
"rmi://localhost/"; 
    try { 
      Context namingContext = new InitialContext(); 
      // 检索指定的对象。 即找到服务器端相对应的服务对象存根 
      IService service02 = (IService) namingContext.lookup(url 
          + "service02"); 
      Class stubClass = service02.getClass(); 
      System.out.println(service02 + " 是 " + stubClass.getName() 
          + " 的实例!"); 
      // 获得本底存根已实现的接口类型 
      Class[] interfaces = stubClass.getInterfaces(); 
      for (Class c : interfaces) { 
        System.out.println("存根类实现了 " + c.getName() + " 接口!"); 
      } 
      System.out.println(service02.service("你好!")); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
}
 
将以上代码保存于某一目录下,先运行“
start rmiregistry
”来启动
JDK
自带的注册表程序,它用于保存
Server
类注册的远程对象并允许远程客户端的请求访问;然后运行服务器端的
Server
类,即“
start java Server
”,该程序向注册表中注册具体的远程对象;最后才是运行客户端程序来查找并获得服务器端的远程对象存根,此时才能使用存根对象与服务器进行通信,命令是“
java Client
”。注意:上面命令中的start的功能是重新打开一个
DOS
窗口。
运行结果如下:
 
 
其实整个简单的
RMI 
应用中各个类的交互时序如下图:
以上内容是学习参考了孙卫琴老师的《Java网络编程精解》一书的RMI一章,加上了自己个人的理解总结,希望能与大家互相学习共同进步!

本文出自 “” 博客,请务必保留此出处

转载地址:http://pebda.baihongyu.com/

你可能感兴趣的文章
WilliamChart各种图表效果实现大全《IT蓝豹》
查看>>
shell脚本——linux主机监控
查看>>
eclipse配置jsp页面模板
查看>>
基于高德地图写的不同功能的地图应用
查看>>
DHCP服务器配置
查看>>
快速瓶颈识别
查看>>
运维工作总结201403
查看>>
我是菜鸟我加油……mysql主从同步
查看>>
[体系结构]设计模式(五)
查看>>
分布式文件系统
查看>>
其实很简单 微星为你详解Z77主板BIOS设置
查看>>
在Ubuntu Kylin下安装JDK1.8
查看>>
Hadoop 学习一
查看>>
Linux中生成/etc/shadow的加密密码
查看>>
《gcc五分钟系列》第三节:-o选项
查看>>
批量检测主机存活状态
查看>>
解决 error: gnu/stubs-32.h: No such file or directory
查看>>
imread 函数 的相关细节
查看>>
分布式和事务
查看>>
C#学习常用类(1002)---KeyValuePair<TKey, TValue> 结构
查看>>