RMI(Remote Method Invocation)與 CORBA 是兩大主流分散式物件架構。C/S 模式需自行設計通訊協定(如 HTTP),而分散式物件模式透過定義介面隔離客戶端請求與伺服器服務,RMI 與 CORBA 皆屬此模型。
RMI 讓開發者如同呼叫本地方法般呼叫遠端物件,無需定義協定,大幅簡化 Socket 開發複雜度。
// FileInterface.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface FileInterface extends Remote {
public byte[] downloadFile(String fileName) throws RemoteException;
}
注意:介面必須 public、繼承 Remote、方法拋出 RemoteException。
// FileImpl.java
import java.io.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class FileImpl extends UnicastRemoteObject implements FileInterface {
private String name;
public FileImpl(String s) throws RemoteException { super(); name = s; }
public byte[] downloadFile(String fileName) {
try {
File file = new File(fileName);
byte[] buffer = new byte[(int)file.length()];
try (BufferedInputStream input = new BufferedInputStream(new FileInputStream(fileName))) {
input.read(buffer, 0, buffer.length);
}
return buffer;
} catch (Exception e) {
System.out.println("FileImpl: " + e.getMessage());
e.printStackTrace();
return null;
}
}
}
繼承 UnicastRemoteObject 表示單一、不可複製、透過 TCP 傳輸的 RMI 物件。
// FileServer.java
import java.rmi.*;
public class FileServer {
public static void main(String[] argv) {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try {
FileInterface fi = new FileImpl("FileServer");
Naming.rebind("//127.0.0.1/FileServer", fi); // 預設埠 1099
} catch (Exception e) {
e.printStackTrace();
}
}
}
若 Registry 在其他埠:Naming.rebind("//127.0.0.1:4500/FileServer", fi)。
// FileClient.java
import java.rmi.*;
public class FileClient {
public static void main(String[] argv) {
if (argv.length != 2) {
System.out.println("Usage: java FileClient fileName MachineName");
System.exit(0);
}
try {
String name = "//" + argv[1] + "/FileServer";
FileInterface fi = (FileInterface) Naming.lookup(name);
byte[] filedata = fi.downloadFile(argv[0]);
try (BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(argv[0]))) {
output.write(filedata, 0, filedata.length);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
rmic FileImpl(產生 FileImpl_Stub.class、FileImpl_Skel.class)rmiregistry 1099java -Djava.security.policy=policy.txt FileServerjava FileClient fileName MachineName安全策略範例(policy.txt):
grant {
permission java.security.AllPermission "", "";
};
RMI 讓遠端方法呼叫如同本地呼叫般直觀,適合純 Java 環境的分散式應用。下篇將介紹 CORBA 的跨語言整合能力。