如果要我们手动去实现这些步骤,将遇到一个很大的编码难题:必须设计一种传输格式,还必须为数据与该传输之间的转换而编码,幸运的是在Web应用中W3C设计出了HTTP协议,浏览器厂商遵循HTTP协议能解析HTTP响应,Web服务器厂商也遵循HTTP协议能够解析客户端提交的请求并作出响应返还给浏览器。而程序员只要遵循HTTP协议与相应Web服务器技术规范就能实现浏览器与Web服务器之间的通信,而底层的交互都由遵循HTTP协议Web服务器与浏览器完成了。
我们需要的也是一种类似的机制,客户端程序员以常规的方式进行方法调用,而无而操心数据在网络上传输或者解析响应之类的问题,但问题是,提供服务的对象可能不在同一个 虚拟机内,甚至,它可以不是Java语言实现的对象。其解决办法是,在客户端为服务对象安装一个代理(proxy),客户端调用此代理,而代理对象负责与服务器联系。同理,编写服务器对象的程序员也不想因与客户端之间的通信而被绊住,解决办法是在服务端安装第二个代理对象,该服务器代理与客户端代理进行通信,并且它将以常规方式调用服务器对象上的方法,如下图:
vcC0seDC67Xa0ru49rLOyv2jrNTaUk1J0K3S6dbQyv3X1tfcysfS1LTzzrLK/beo19a92suz0PK3osvNo6y2+LbUz/PU8sq508NKYXZhtcTQ8sHQu6+7+tbGvfjQ0LHgwuu1xKGjttSyzsr9tcSx4MLruf2zzLPGzqqyzsr9seDX6ShwYXJhbWVyZXIgbWFyc2hhbGxpbmcpo6yyzsr9seDX6bXExL+1xMrHvauyzsr916q7u7PJysq6z9Ta0OnE4rv61q685L340NC0q7XdtcQmIzI2Njg0O8q9oaM8YnI+CtK7tM7UtrPMt723qLX308O1xMH3s8zOqqO6v827p7bLtcS05rj5t723qLm51OzBy9K7uPbQxc+iv+mjrMv808nS1M/CvLiyv7fW1+mzyaO6PGJyPgphLrG7yrnTw7XE1LazzLbUz/O1xLHqyra3+6O7PGJyPgpiLrG7tffTw7XEt723qLXEw+jK9js8YnI+CmMuseDX6brztcSyzsr9oaM8YnI+Csi7uvOjrLTmuPm9q7TL0MXPoreiy824+Lf+zvHG96Os1Nq3/s7xxve2y6Os0ru49r3TytW21M/zzqrDv7j21LazzLe9t6i199PD1rTQ0NLUz8K2r9f3o7o8YnI+CmEut7Sx4Nfpss7K/Txicj4KYi62qM670qq199PDtcS21M/zPGJyPgpjLrK2u/G3tbvYJiMyMDU0MDu78rjDtffTw7L6yfq1xNLss6OjrLKittTL/LHg1+mjuzxicj4KZC69q7e1u9gmIzIwNTQwO7Hg1+mjrLTysPzLzbvYuPi/zbuntsu05rj5oaM8YnI+Csjnzbyjujxicj4KPGltZyBzcmM9"https://www.cppentry.com/upload_files/article/76/1_jadvx__.jpg" alt="\">
下面是远程方法调用的一个例子:
在Java中一个对象要能够用于远程调用,有一定限制,远程对象所在类必须实现接口,并且该接口一定要继承java.rmi.Remote;接口而该类通常都会继承自java.rmi.server.RemoteServer类,而该类是一个抽象类,它只定义了服务器对象与远程存根通信的基本机制,而java.rmi.server.UnicastRemoteObject 继承自RemoteServer类,UnicastRemoteObject不是抽象类故而可以直接使用它,所以我们真正继承的是java.rmi.server.UnicastRemoteObject类,下面就是一个远程服务器类:
public interface Product extends Remote {
String getDescription() throws RemoteException;
}
public class ProductImpl extends UnicastRemoteObject implements Product {
private static final long serialVersionUID = -2489180038994927428L;
private String desc;
public ProductImpl(String desc) throws RemoteException {
this.desc = desc;
}
public String getDescription() throws RemoteException {
return "I am a " + desc + ". Buy me!";
}
}
下面启动RMI服务端:
public class ProductServer {
public static void main(String[] args) throws Exception {
LocateRegistry.createRegistry(1099);
System.out.println("Constructing server implementations...");
ProductImpl p1 = new ProductImpl("Blackwell Toaster");
ProductImpl p2 = new ProductImpl("ZapXpress Microwave Oven");
System.out.println("Binding server implementations to registry...");
Context namingContext = new InitialContext();
namingContext.bind("rmi:toaster", p1);
namingContext.bind("rmi:microwave", p2);
System.out.println("Waiting for invocations from clients...");
}
}
LocateRegistry.createRegistry(1099);必须为RMI注册端口号,RMI默认的端口号就为1099,否则服务器会拒绝连接。如果要修改默认的调用器可以显示调用UnicastRe