如果你不用代码进行注册也可以在命令行输入命名rmiregistry 1099,其效果与代码注册是一样的。
namingContext.bind("rmi:toaster", p1);为对远程对象进行绑定,只有进行了绑定客户而才能通过相应的标识符进行查找到远程对象存根。绑定也可以调用Naming.bind()方法,在JDK1.3以后RMI命名服务被整合到了JNDI中。
运行main方法就可以启动服务端。
下面编写客户端:
public class ProductClient {
public static void main(String[] args) throws Exception {
System.setProperty("java.security.policy", "client.policy");//指定安全策略文件
System.setSecurityManager(new RMISecurityManager());//注册安全管理器
String url = "rmi://127.0.0.1:1099/";
Context namingContext = new InitialContext();
Product p1 = (Product) namingContext.lookup(url+"toaster");//查找远程对象,其实得到的是一个存根对象,该存根实现了相应的接口
System.out.println(p1.getClass());
Product p2 = (Product) namingContext.lookup(url+"microwave");
System.out.println(p1.getDescription());
System.out.println(p2.getDescription());
}
}
使用RMI的客户端程序要安装一个安全管理器,用以控制动态加载存根的行为,RMISecurityManager就是这样的一安全管理器,安装代理很简单System.setSecurityManager(new RMISecurityManager());( Java程序默认是没有安全管理器的)默认情况下RMISecurityManager将对程序中建立网络连接的所有代码进行限制,然而,程序需要建立网络连接以达到RMI注册表与联系服务器对象,所以我们要通过指一定个策略文件来允许客户端连接RMI注册表以及服务器对象。策略文件如下:
grant {
permission java.net.SocketPermission "*:1024-65535", "connect";
};
文件名可以任意,在程序中我们指定的文件名为client.policy,如果你是用eclipse运行客户端请将该策略文件放置在项目根路径下,如果你是以命令行运行请将策略文件放置在类根路径下,否则会找不到策略文件而访问遭拒绝。
除了可以设置 系统属性指定策略文件外也可以在运行java使命的时候通过设置运行参数指定,如:java -Djava.security.policy=client.policy xxx.xxx.ProductClient这时的路径是相对于命令窗口所在目录的。
如果使用的是JDK1.4或更低的版本,客户端存根类是要通过rmic命令进行生成的,如:rmic xxx.xxx.ProductImpl,注意编译的是类这样会生成一个名为xxx.xxx.ProductImpl_Sub的类,然后将这个类放置在客户端类路径上,但在JDK1.5开始,该存根类可以通过动态代理生成,就不需要执行rmic命令了。当然如果这时你就是要运行rmic命令也是可以的,这样客户端还是会使用该命令生成的存根类而不使用动态代理。
运行客户端main方法应该就可以看到相应的输出了。
如果你把这个例子把服务端搬到另一台机器上可能会报java.rmi.ConnectException: Connection refused to host: 127.0.0.1异常,至于原因,请参看:异常原因