远程方法调用(Remote Method Invocation,RMI)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
一个正常工作的RMI系统由下面几个部分组成:·
.远程服务的接口定义
·远程服务接口的具体实现
·桩(Stub)和框架(Skeleton)文件
·一个运行远程服务的服务器
·一个RMI命名服务,它允许客户端去发现这个远程服务
·类文件的提供者(一个HTTP或者FTP服务器)
·一个需要这个远程服务的客户端程序
要完成以上步骤需要有以下几个步骤:
1、生成一个远程接口
2、实现远程对象(服务器端程序)
3、生成占位程序和骨干网(服务器端程序)
4、编写服务器程序
5、编写客户程序
6、注册远程对象
7、启动远程对象
1. 创建远程接口及声明远程方法(TimerServiceInterface.java)
package com.weiythi.service; import java.rmi.Remote; import java.rmi.RemoteException; public interface ITimeService extends Remote{ public long getTime() throws RemoteException; }
2. 实现远程接口及远程方法(继承UnicastRemoteObject)TimerService.java
package com.weiythi.service; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class TimerService extends UnicastRemoteObject implements ITimeService{ private static final long serialVersionUID = 1L; /** * 必须定义构造方法,即使是默认构造方法,也必须把它明确地写出来,因为它必须抛出出RemoteException异常 */ public TimerService() throws RemoteException{ } /** * 接口方法的实现 */ @Override public long getTime() throws RemoteException { return System.currentTimeMillis(); } }
3. 启动RMI注册服务,并注册远程对象
方法一,打开一个DOS窗口,使用rmic命令
rmic com.weiythi.service.TimerService
启动RMI注册服务,指定端口为1099 (1099为默认端口)
start rmiregistry
注册远程对象(HelloServer.java)
package com.weiythi.service; import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; public class StartTimerServer { public static void main(String[] args){ try { TimerService timerservice=new TimerService(); //把TimerService注册到RMI注册服务器上,命名为b1 Naming.bind("b1", timerservice); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (AlreadyBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }方法二: package com.weiythi.service;
import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; public class StartTimerServer { public static void main(String[] args){ try { //启动RMI注册服务 //也可以通过命令 start rmigesitry启动 //这里用这种方式避免了再打开一个DOS窗口 //而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用 LocateRegistry.createRegistry(1099); TimerService timerservice=new TimerService(); //把TimerService注册到RMI注册服务器上,命名为b1 Naming.bind("b1", timerservice); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (AlreadyBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }4. 客户端查找远程对象,并调用远程方法(GetTimerService.java)package com.weiythi.client;
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import com.weiythi.service.ITimeService; public class GetTimerService { public static void main(String[] args){ try { ITimeService time=(ITimeService) Naming.lookup("rmi://localhost/b1"); System.out.println("the time is:"+time.getTime()); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NotBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }