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类是最终负责注册服务器远程对象,以便在服务器端存在骨架代理对象来对客户端的请求提供处理和响应。
各个类的源代码如下:
import java.rmi.Remote; import java.rmi.RemoteException; public interface IService extends Remote { // 声明服务器端必须提供的服务 public String service(String content) throws RemoteException; } import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; //UnicastRemoteObject用于导出的远程对象和获得与该远程对象通信的存根。 public class ServiceImpl extends UnicastRemoteObject implements IService { private String name; protected ServiceImpl(String name) throws RemoteException { this.name = name; } @Override public String service(String content) throws RemoteException { System.out.println(content + " --------- 我被客户端调用了 ---------"); return "server------>" + content; } } import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class Server { public static void main(String[] args) { try { // 实例化实现了IService接口的远程服务ServiceImpl对象 IService service01 = new ServiceImpl("service01"); // 初始化命名空间 Context ct = new InitialContext(); LocateRegistry.createRegistry(8888); // 将名称绑定到对象,即向命名空间注册已经实例化的远程服务对象 ct.rebind("rmi://127.0.0.1:8888/service01", service01); System.out.println(">>>>>INFO:远程service对象绑定成功!>>>>>"); } catch (RemoteException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } } } import javax.naming.Context; import javax.naming.InitialContext; public class Client { public static void main(String[] args) { String url = "rmi://localhost:8888/"; try { Context ct = new InitialContext(); // 检索指定的对象 即找到服务器端相对应的服务对象存根 IService service = (IService) ct.lookup(url + "service01"); System.out.println(service + " is :" + service.getClass().getName() + " instance"); Class<?>[] sInterfaces = service.getClass().getInterfaces(); for (Class<?> clazz : sInterfaces) { System.out.println(" interface is " + clazz.getName()); } String str = service.service("你好"); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } }
其实整个简单的RMI 应用中各个类的交互时序如下图:
推荐一篇更完善的文章:http://ryxxlong.iteye.com/blog/1560535
相关推荐
java rmi java rmijava rmi javajava rmi java rmi rmi
JavaRMI的原理和实现方法 分布式对象计算 来源于青岛大学学报
java RMI技术实现的网络聊天室 编译通过,很完整的。代码很有参考价值
采用JAVA rmi,带图形界面,完全由自己实现的聊天室,具备基本的聊天功能,可以自己扩充功能
检测javaRMI反序列化漏洞
java RMI
java RMI实现代码。分为客户端和服务器端,有清楚的代码注释。
Java RMI 简单示例
JavaRMI.pdf
最近在学习代理模式,用到了java rmi远程调用,包含服务端和客户端,之前一直没有接触过,学习了java rmi远程调用,一方面可以了解代理模式,一方面熟悉java低层的远程
《Java RMI》一书的英文版本,With Java RMI, you'll learn tips and tricks for making your RMI code excel. This book provides strategies for working with serialization, threading, the RMI registry, ...
javaRMI完整版.pdf
Java RMI实例
这是本人搜集整理的Java RMI规范,中文版,经过排版 共包括10个章节,2个附录
JAVARMI实例[文].pdf
在这次的项目中,对于客户端与服务器之间的通信,想了许多办法,由于做的是富客户端应用,最终将技术选定在了RMI和Java-sockets两种之间,其中RMI的灵活性不高,客户端和服务器端都必须是java编写,但使用比较方便,...
这是原创的最简单的Java RMI入门项目,内含二个Eclipse项目,一是服务器端,二是客户端。非常简单,只看其中的注释就能理解(当然先要知道什么是RMI了),只供入门用。 这是用Java 1.7编辑的,如果你用的版本低,则...
Java RMI的应用——学习RMI的简单编程应用。编写一个课程成绩管理程序,要求用Java RMI实现
我的博客《Java中的RMI(远程方法调用)》的示例代码
JAVA RMI PDF