接口
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IFoo extends Remote {
String say(String name) throws RemoteException;
}
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IBar extends Remote {
String buy(String name) throws RemoteException;
}
实现
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class FooImpl /* extends UnicastRemoteObject */ implements IFoo {
private int index;
public FooImpl() throws RemoteException {
this(0);
}
public FooImpl(int port) throws RemoteException {
// ObjectTable.objTable
UnicastRemoteObject.exportObject(this, port);
}
@Override
public String say(String name) throws RemoteException {
String message = "say" + (index++);
System.out.println(message);
return name + ": " + message;
}
}
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class BarImpl implements IBar {
private int index;
public BarImpl() throws RemoteException {
this(0);
}
public BarImpl(int port) throws RemoteException {
// ObjectTable.objTable
UnicastRemoteObject.exportObject(this, port);
}
@Override
public String buy(String name) throws RemoteException {
String message = "buy" + (index++);
System.out.println(message);
return name + ": " + message;
}
}
两个对象实例化之后, 观察 ObjectTable 类里的 objTable 和 implTable 属性内容
// sun.rmi.transport.ObjectTable
public final class ObjectTable {
private static final Map<ObjectEndpoint, Target> objTable = new HashMap();
private static final Map<WeakRef, Target> implTable = new HashMap();
}
ObjectTable.objTable 属性内容
ObjectTable.implTable 属性内容
Server
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException {
IBar bar = new BarImpl();
IFoo foo = new FooImpl();
//方式一
Registry registry = LocateRegistry.createRegistry(58082);
registry.bind("bar", bar);
//方式二
Naming.bind("rmi://192.168.31.141:58082/foo", foo);
}
}
bind 方法会向 RegistryImpl的Hashtable<String, Remote> bindings属性put操作
执行Server的main方法之后, 服务端 registry 对象的属性如下
ObjectTable.objTable 属性内容里多了一个RegistryImpl_Stub
服务端会有一个线程(RMI TCP Accept-58082) 监听 58082 端口, 等待客户端的请求
客户端
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) throws Exception {
//方式一
Registry registry = LocateRegistry.getRegistry("192.168.31.141", 58082);
IFoo foo = (IFoo) registry.lookup("foo");
System.out.println(foo.say("druid"));
//方式二
IBar bar = (IBar) Naming.lookup("rmi://192.168.31.141:58082/bar");
System.out.println(bar.buy("hikari"));
}
}
参考文献