java 远程方法调用(RMI)
- 什么是RMI?
维基百科:一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。
- 什么是序列化及反序列化
(1)序列化:把对象转换为字节序列的过程称为对象的序列化。
(2)反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
对象序列化用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
- RMI远程调用步骤:
1),客户对象调用客户端辅助对象(stub对象)上的方法;
2),客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象(skeleton对象);
3),服务端辅助对象将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象;
4),调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象;
5),服务端辅助对象将结果打包,网络发送给客户端辅助对象;
6),客户端辅助对象将返回值解包,返回给客户对象;
7),客户对象获得返回值;
- RMI实例:
共同部分,包含Person.java,ImyRemote.java;
import java.io.Serializable; public class Person implements Serializable { /** * 序列化ID */ private static final long serialVersionUID = -3245478690496182643L; public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
import java.rmi.Remote; import java.rmi.RemoteException; public interface IMyRemote extends Remote { String sayHello() throws RemoteException; Person getPerson() throws RemoteException; }
Server部分,包含MyRemoteImpl.java,Server.java:
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class MyRemoteImpl extends UnicastRemoteObject implements IMyRemote { public MyRemoteImpl() throws RemoteException { } @Override public String sayHello() { return "server say,hello world"; } @Override public Person getPerson() throws RemoteException { return new Person("张三",18); } }
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.RemoteException; public class Server { public static void main(String[] args) { try{ // LocateRegistry.createRegistry(1099); IMyRemote iRemote = new MyRemoteImpl(); Naming.rebind("rmi://198.181.47.219:1099/remoteServer", iRemote); System.out.println("绑定成功"); }catch (RemoteException e){ System.out.println("RemoteException"); e.printStackTrace(); } catch (MalformedURLException e) { System.out.println("MalformedURLException"); e.printStackTrace(); } } }
Client部分,包含Client.Java:
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class Client { public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException { IMyRemote client = (IMyRemote) Naming.lookup("rmi://198.181.47.219:1099/remoteServer"); System.out.println(client.sayHello()); Person p = client.getPerson(); System.out.println("name:" + p.getName() + "age:" + p.getAge()); } }
注:
(1) 启动远程服务前,需要先启动rmiregistry(Naming.rebind注册服务,rmiregistry必须运行);
(2)传输的对象的类型必须成为可序列化类型(编译器无法发现);