Java RMI原理与使用
2016-06-28 14:10
375 查看
Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。
Java RMI概念
在Java中,只要一个类继承了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展
java.rmi.Remote 的接口)中指定的这些方法才可远程使用。
编写一个RMI的步骤
1. 定义一个远程接口,此接口需要继承Remote 2. 开发远程接口的实现类 3. 创建一个server并把远程对象注册到端口 4. 创建一个client查找远程对象,调用远程方法
一个Hello Word的远程调用实例
定义一个远程接口
编写RMI应用的第一步就是先定义远程接口。远程接口必须继承java.rmi.Remote接口,并且声明自己的远程方法。为了处理远程方法发生的各种异常,每一个远程方法必须抛出一个
java.rmi.RemoteException异常。
public interface RemoteHelloWord extends Remote { String sayHello() throws RemoteException; }
这个远程接口只定义了一个远程方法
sayHello(),远程方法在调用的时候有可能失败比如发生网络问题或者server挂掉,此时远程方法会抛出
RemoteException异常。
开发接口的实现类
开发接口的实现类,即具体的远程对象,在远程对象中实现远程接口中定义的方法。public class RemoteHelloWordImpl implements RemoteHelloWord{ @Override public String sayHello() throws RemoteException { return "Hello Word!"; } }
创建一个Server并把对象注册到端口
在server端只需要做两件事:创建并导出远程对象
用Java RMI registry 注册远程对象
下面是一个server端的程序:
public class RMIServer { public static void main(String[] args) { try { RemoteHelloWord hello=new RemoteHelloWordImpl(); RemoteHelloWord stub=(RemoteHelloWord)UnicastRemoteObject.exportObject(hello, 9999); LocateRegistry.createRegistry(1099); Registry registry=LocateRegistry.getRegistry(); registry.bind("helloword", stub); System.out.println("绑定成功!"); } catch (RemoteException e) { e.printStackTrace(); } catch (AlreadyBoundException e) { e.printStackTrace(); } } }
关于创建和导出远程对象
RemoteHelloWord stub=(RemoteHelloWord)UnicastRemoteObject.exportObject(new RemoteHelloWordImpl(), 0);
Server端的main方法在创建一个远程对象来提供服务时,此远程对象必须被导出才能被远程调用者调用。静态方法
UnicastRemoteObject.exportObject()负责导出我们定义好的远程对象,并用任意一个tcp端口来接收远程方法调用,同时,它还会返回一个存根,这个存根将会发送给client端进行调用。当
exportObject()方法被执行后,运行时会在一个新的Server
Socket或共享Server Socket上进行监听,来接收对远程对象的远程调用。返回的存根对象和远程对象继承的是同一套remote接口(为了实现代理模式),并且还它还包含了供client端口访问的主机IP和端口信息。
用Java RMI registry注册远程对象
Registry registry=LocateRegistry.getRegistry(); registry.bind( "helloword", stub);
为了使client能够调用远程对象的方法,client必须持有远程对象的存根,为此,Java RMI 提供了registry API 可以允许应用程序把一个名称和远程对象的存根绑定在一起,这样client就可以通过这个绑定的名称很方便的查找到需要调用的远程对象了,在这里可以把registry看做是一个名称服务,实现了工厂模式(提供具体的远程对象)和代理模式(代理server端具体处理client端的请求)。
一旦远程对象在server端导出并注册,client就可以通过绑定的名称获得远程对象的引用,然后调用远程方法。
静态方法
Registry registry=LocateRegistry.getRegistry()会返回一个实现了
java.rmi.registry.Registry接口的存根,并且在服务器本机的端口(默认是1099)上进行注册,返回的registry存根通过调用bind()方法在registry中把一个字符串名称和远程对象存根绑定在一起。
创建一个client查找远程对象,调用远程方法
public class RMIClient { public static void main(String[] args) { try { Registry registry = LocateRegistry.getRegistry("localhost"); RemoteHelloWord hello = (RemoteHelloWord) registry.lookup( "helloword"); String ret = hello.sayHello(); System. out.println( ret); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } }
}
客户端首先通过
LocateRegistry.getRegistry("localhost")方法获得registry的存根,然后再执行registry存根的
lookup()方法从服务器registry中获得远程对象的存根,最后客户端在远程对象存根上执行
sayHello()方法。整个过程可以描述为:
客户端通过远程对象存根中的IP和端口打开一个服务器连接,并且序列化请求数据
服务器端接收请求并且转发请求到远程对象调用服务方法,并且序列化运行结果发送给客户端
客户端接收数据反序列化,把最终结果返回给调用者
结果测试
启动server,然后在启动client,控制台打印:Hello Word!
Java RMI中用到的设计模式
Java RMI中用到了经典的工厂模式和代理模式,先介绍下Java RMI应用的一些角色:server:生产各种远程对象
client:通过命名服务器rmiregistry获取远程对象的存根
rmiregistry:具体处理client与server的交流
下面这幅图演示了整个步骤,下图中先做如下假设:
有两个远程服务接口可供client调用,Factory和Product接口
FactoryImpl类实现了Factory接口,ProductImpl类实现了Product接口
1. FactoryImpl被注册到了rmiregistry中 2. client端请求一个Factory的引用 3. rmiregistry返回client端一个FactoryImpl的引用 4. client端调用FactoryImpl的远程方法请求一个ProductImpl的远程引用 5. FactoryImpl返回给client端一个ProductImpl引用 6. client通过ProductImpl引用调用远程方法
相关文章推荐
- jdk 多版本安装 for mac
- Eclipse Class Decompiler——Java反编译插件
- java安全框架-Shiro学习笔记(八)-加密工具类
- Java---Condition控制线程通信
- Java NIO 详解(二)
- Java IO
- Java8系列之重新认识HashMap
- Java NIO 详解(一)
- Java细粒度锁实现的3种方式
- java Excel导入导出,基于XML的实现,easy-excel使用
- JavaWeb学习总结(五十三)——Web应用中使用JavaMail发送邮件
- JavaWeb学习总结(五十二)——使用JavaMail创建邮件和发送邮件
- Java8的伪共享和缓存行填充--@Contended注释
- JavaWeb学习总结(五十)——文件上传和下载
- JavaWeb学习总结(四十九)——简单模拟Sping MVC
- JavaWeb学习总结(四十八)——模拟Servlet3.0使用注解的方式配置Servlet
- java web开发 高并发处理
- Java运行可执行文件
- javaweb学习总结(四十七)——监听器(Listener)在开发中的应用
- Java中关于类的一个小问题