RMI初步
RMI(remote method Invocation)自从Java1.1便出现了,是Java之间远程调用的基础,EJB便是构建在其基础上的。但只能是Java对象之间的RPC,不支持异构系统调用。当然,异构系统之间的调用我们一般用WebServices(在通信、金融行业也有广泛使用重量级的CORBA作为解决方案)。其实无论是异构系统的RPC还是JVM之间的RMI,核心思想都是类似的,主要是Stub和Skeleton对象在近端和远端充当中介。在RMI中这两个对象在底层处理了,对程序员是透明的。我们使用一个简单的例子描述RMI的简单使用方法,下一篇文章我们描述项目中一个真实的应用:Flex+RMI开发的一个简单的自动化部署工具。用于将程序快速发布到数十台集群机器上。
OK,我们先看简单的demo(代码是在记事本中手写的,注释不全请海涵):
1、远程对象接口,在Client端依赖查找到的也是接口类型:
import java.rmi.Remote; import java.rmi.RemoteException; //远程对象接口 public interface Bean extends Remote{ public String sayHello()throws RemoteException; public String sayHello(String name)throws RemoteException; };
2、远程对象实现类
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; //远程对象实现类 public class BeanImpl extends UnicastRemoteObject implements Bean{ public BeanImpl()throws RemoteException { }; public String sayHello(){ return "hello!"; } public String sayHello(String name){ return "hello,"+name+"!"; } };
3、Server端
import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.Naming; public class Server{ public static void main(String []args)throws Exception{ //构造待调用的远端对象,注册端口并绑定 Bean bean = new BeanImpl(); LocateRegistry.createRegistry(8888); String url = "//127.0.0.1:8888/server"; Naming.bind(url,bean); } };
4、Client端类:
import java.rmi.Naming; public class Client{ public static void main(String []args)throws Exception{ String url = "//192.168.1.145:8888/server"; System.out.print("查找地址为"+url+"的对象:"); Bean bean = (Bean)Naming.lookup(url); System.out.println(bean); System.out.println("调用远程对象无参方法:"+bean.sayHello()); System.out.println("调用远程对象有参方法:"+bean.sayHello("digitalChina")); } };
演示:
1、将Server.java、Bean.java、BeanImpl.java 在一个内网ip为192.168.1.145的机器上编译(我用命令行javac),然后java Server运行起来(此时RMI底层已经在8888端口监听了)
2、将Client.java、Bean.java在内网ip为192.168.1.112的另一台机器上编译,然后执行java Client。
上面的代码我们可以看见,在Client的main方法中,我们使用RMI获取了一个Bean接口类型的对象,然后调用了两次该对象的方法:
从上面的输出我们可以看出,使用Naming.lookup查找到的是代理对象Proxy。
如果遇到access denyed异常,则可能是JDK对server端安全控制的问题,需在起Server的时候指定安全策略:
[root@localhost RMISERVER]# java -Djava.security.policy=rmi.policy Server &
其中rmi.policy的内容
grant { permission java.net.SocketPermission "*:8888","connect,accept,resolve"; };
OK,至此,一个简单RMI的demo就这样Run起来了。下一篇文章《近两年项目回顾系列——基于Flex和RMI的自动化部署工具 》大体描述一下我们基于RMI开发的一个自动化部署小工具。