Java 2 Enterprise Edition(J2EE)遠程方法調用(Remote Method Invocation,RMI)框架允許你創建透明的、分布式的服務和應用程序。基於RMI的應用程序由Java對象構成,這些對象相互調用,同時忽略對方的位置。換言之,一個Java對象可調用另一個虛擬機上的某個Java對象的方法,整個過程和調用同一個虛擬機上的某個Java對象的方法無異。駐留在不同虛擬機上的對象為了相互獲得引用,可以使用RMI的查找服務,或者將對象引用作為方法調用的一個參數或者返回值來接收。參數和返回值借助Java的對象序列化機制由RMI來進行封送。
遠程對象和接口
Java提供了一個完全限定名稱為java.rmi.Remote的接口。任何對象要想參與和另一個Java對象的遠程會話,就必須直接或間接地實現該接口。尤其要注意的是,任何由java.rmi.Remote接口來標識的對象都暗示著它的方法可從其他任何虛擬機進行調用。實現了java.rmi.Remote接口的對象通常稱為“遠程對象”,必須采用以下方式來聲明它的方法:
每個支持遠程調用的方法都必須在其throws子句中聲明java.rmi.RemoteException。
對於一個可遠程調用的方法,它的每個非基本(nonprimitive)參數或者返回值都必須直接或間接地聲明為實現了java.io.Serializable接口。
除了實現java.rmi.Remote接口和正確聲明任何遠程方法之外,遠程對象必須提供一個無參數的構造函數,它能引發一個java.rmi.RemoteException異常。這就保證了對象可基於一種序列化狀態來遠程構造。
遠程對象必須導出,以接收傳入的遠程方法調用。為此,你通常需要擴展java.rmi.server.UnicastRemoteObject或者java.rmi.activation.Activatable。通過對其中任何一個類進行擴展,遠程對象就可在創建時自動導出。
以下接口定義展示了java.rmi.Remote接口最典型的用法:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface TimeKeeper extends Remote
{
public String currentDate() throws RemoteException;
public String currentTime() throws RemoteException;
}
由於String類聲明為實現了java.io.Serializable接口,所以String是遠程方法的有效返回類型。
以下代碼展示了如何實現TimeKeeper接口,以便定義一個有效的遠程對象:
import java.rmi.RemoteException;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class TimeKeeperImpl implements TimeKeeper
{
public TimeKeeperImpl()
throws RemoteException
{
}
public String currentDate() throws RemoteException
{
Calendar cal = new GregorianCalendar();
String retVal = (cal.get(Calendar.MONTH) + "/" +
cal.get(Calendar.DAY_OF_MONTH) + "/" +
cal.get(Calendar.YEAR));
return retVal;
}
public String currentTime() throws RemoteException
{
Calendar cal = new GregorianCalendar();
String retVal = (cal.get(Calendar.HOUR_OF_DAY) + ":" +
cal.get(Calendar.MINUTE) + ":" +
cal.get(Calendar.SECOND));
return retVal;
}
}