搬运维基百科的代码,已实际测试过。记录下一些注意事项
- 远程服务接口需要继承 java.rmi.Remote
- 接口方法需要申明抛出java.rmi.RemoteException,
- 接口方法参数或返回值的class类型需要实现序列化接口即java.io.Serializable或者为八种基本数据类型。
- 远程调用时是通过序列化的方法传递数据,int类型可能会被转换为double类型
- 远程调用参数或返回值的class类型必须两个jvm中都有。这里的class类型是实例的具体类型,而不是申明类型,匿名类,由spring框架切面生产的代理类都会报错。
下述代码仅为本地localhost测试,实际不同主机使用时,需要考虑权限问题。
package study.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RmiServerIntf extends Remote {
public String getMessage() throws RemoteException;
}
package study.rmi;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
public class RmiServer extends UnicastRemoteObject implements RmiServerIntf {
public static final String MESSAGE = "Hello World";
public RmiServer() throws RemoteException {
super(0); // required to avoid the 'rmic' step, see below
}
@Override
public String getMessage() {
return MESSAGE;
}
public static void main(String args[]) throws Exception {
System.out.println("RMI server started");
try { //special exception handler for registry creation
LocateRegistry.createRegistry(1099);
System.out.println("java RMI registry created.");
} catch (RemoteException e) {
//do nothing, error means registry already exists
System.out.println("java RMI registry already exists.");
}
//Instantiate RmiServer
RmiServer obj = new RmiServer();
// Bind this object instance to the name "RmiServer"
Naming.rebind("//localhost/RmiServer", obj);
System.out.println("PeerServer bound in registry");
}
}
package study.rmi;
import java.rmi.Naming;
public class RmiClient {
public static void main(String args[]) throws Exception {
RmiServerIntf obj = (RmiServerIntf) Naming.lookup("//localhost/RmiServer");
System.out.println(obj.getMessage());
}
}