RMI 学习笔记

来源:互联网 发布:java try的教学 编辑:程序博客网 时间:2024/05/22 17:30

 RMI(Remote Method Invocation)远程方法调用是java的核心技术之一。是Enterprise JavaBeans的基础技术,是java建立分布式应用程序的强大支柱。

RMI允许一个应用程序访问另外一个服务器或虚拟机上的对象,方法和服务,它使远程方法调用就像在本地调用一样简单。它为用户屏蔽了底层的网络传输细节,使用的时候只需适当处理异常即可。所以RMI是非常容易使用的,但同时是非常强大的。

 

下面通过一个简单的例子初步认识RMI。

情景:通过ATM查询账户余额。

分析:假如使用RMI实现(只是假如),ATM机需要通过我的银行卡的卡号查询账户余额,

对应的有一个BankService之类的类,提供了一个叫queryBalance的方法,而这个对象存活于某个远程服务器

的虚拟机上,RMI的作用就是,ATM调用这个远程方法,就像调用本地的方法一样。

实现:

标准步骤如下

1 定义远程接口。需要提供远程服务的对象必须实现该接口。

package rmi.ebank;

 

import java.rmi.Remote;

import java.rmi.RemoteException;

 

public interface EbankRemote extends Remote {

public double queryBalance(String cardId) throws RemoteException;

}

 

2 远程服务的具体实现,即为客户端真正提供服务以供远程调用的对象。

package rmi.ebank;

 

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

 

public class EbankRemoteImpl extends UnicastRemoteObject implements

EbankRemote {

public EbankRemoteImpl() throws RemoteException {

super();

}

public double queryBalance(String cardId) throws RemoteException {

if(cardId.startsWith("card1")) {

return 10000.0;

}else if(cardId.startsWith("card2")) {

return 5000.0;

}

return 0.0;

}

}

这个实现类使用了UnicastRemoteObject去联接RMI系统。在我们的例子中,我们是直接的从UnicastRemoteObject这个类上继承的,

事实上并不一定要这样做,如果一个类不是从UnicastRmeoteObject上继承,那必须使用它的exportObject()方法去联接到RMI。

如果一个类继承自UnicastRemoteObject,那么它必须提供一个构造函数并且声明抛出一个RemoteException对象。

当这个构造函数调用了super(),它久激活UnicastRemoteObject中的代码完成RMI的连接和远程对象的初始化。

 

3 生成Stub和Skeleton

使用rmic编译器生成stub和skeleton,成功执行后会发现一个EbankRemoteImpl_stub.class文件。

如果你是使用的Java2SDK,那么你还可以发现Calculator_Skel.class文件。

具体:开启控制台窗口,进入class目录,运行rmic rmi.ebank.EbankRemoteImpl

 

4 编写服务器端程序并编译。使用JNDI绑定远程服务

package rmi.ebank;

 

import java.net.MalformedURLException;

import java.rmi.RemoteException;

import java.rmi.Naming;

 

public class EbankServer {

 

public static void main(String[] args) {

try {

EbankRemote ebank = new EbankRemoteImpl();

Naming.rebind("rmi://localhost:1099/EbankRemoteService", ebank);

System.out.println("the remote server is ready to supply service.");

} catch (RemoteException e) {

e.printStackTrace();

} catch (MalformedURLException e) {

e.printStackTrace();

}

}

}

 

5 编写客户端程序并编译。此为调用远程服务的客户端,在本例中就是ATM机。

package rmi.ebank;

 

import java.net.MalformedURLException;

import java.rmi.Naming;

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

 

public class EbankClient {

 

public static void main(String[] args) {

try {

EbankRemote ebank = 

(EbankRemote)Naming.lookup(

"rmi://localhost/EbankRemoteService");

System.out.println(ebank.queryBalance("card1"));

System.out.println(ebank.queryBalance("card2"));

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (RemoteException e) {

e.printStackTrace();

} catch (NotBoundException e) {

e.printStackTrace();

}

}

}

 

6 模拟运行RMI系统。由于条件所限,只能在一台机器上模拟,但运行在3个不同的虚拟机上,并不失真。

 开启3个控制台窗口。一个运行RMIRegistry,第二个运行服务器端,第三个运行客户端。

 第一个: 进入class目录,运行rmiregistry命令

 第二个:进入class目录,运行java rmi.EbankServer,屏幕输出:the remote server is ready to supply service.

 第三个:进入class目录,运行java rmi.EbankClient,打印出10000.0  5000.0。

 即使你运行在同一个计算机上,RMI还是使用了你的网络堆栈和TCP/IP去进行通讯,

 并且是运行在三个不同的Java虚拟机上。这已经是一个完整的RMI系统。


原创粉丝点击