RMI技术基础讲解(代理机制)
RMI技术(Remote Methed Invoke):
JAVA RMI技术就是典型的远程代理案例。
RMI提供了客户辅助对象和服务辅助对象,也为客户辅助对象创建了和服务对象相同的方法。RMI的好处是可以不必写任何网络或I/O代码,就可以让客户程序跟在本地JVM正常调用方法一样调用远程方法(真正的服务所在的方法)。但是虽然调用远程方法跟本地一样,但是客户辅助对象还是需要通过网络发送方法调用的,所以网络和I/O还是存在的。
RMI技术的核心:
1、代理技术;
2、反射机制;
3、网络传递参数;
4、网络传递返回值;
5、短连接。
实现原理:
客户端使用代理;执行相关方法时,实质上是通过代理执行的;
在具体被执行的方法中,实际的操作是向服务器发出“请求”:请求
客户端原本要执行的方法。
1、客户端需要连接RMI服务器;
2、向服务器发送要执行的方法的名称、参数类型、参数值;
3、等待服务器返回执行执行结果;这个结果可以看成“响应”。
服务器端必须能够建立服务器,而且不断侦听来自客户端的连接
请求;这个连接请求实质上是客户端发出请求的第一步。接着,
服务器开始接收客户端发来的,对应那个“方法”的名称、参数类
型、参数值;服务器根据客户端发来的上述信息,找到相关方法,
并执行;并且,将执行结果,返回给客户端。
注意:
在RMI的实际工作过程中,客户端只有接口,而不存在,也不需要
存在该接口的实现类!
客户端对RMI的方法的执行,实质上都是传递方法信息和方法参数,
再从服务器端接收结果!
因此,在客户端获取proxy的时候,能提供的仅仅是接口,没有可能
提供该接口实现类。
下面直接看代码:
RMIClient:
这里只是非常简陋的实现了RMIClient,这里主要用到代理机制。通过实现IMethodInvoker接口向对端发送信息(要执行的方法的名称、参数类型、参数值),等待服务器端响应。最后关闭连接。
public class RMIClient {
private String rmiServerIp;
private int rmiServerPort;
public RMIClient() {
}
public void setRmiServerIp(String rmiServerIp) {
this.rmiServerIp = rmiServerIp;
}
public void setRmiServerPort(int rmiServerPort) {
this.rmiServerPort = rmiServerPort;
}
public <T> T getProxy(Class<?> klass) {
MecProxy mecProxy = new MecProxy();
IMethdInvoker methdInvoker = new IMethdInvoker() {
@SuppressWarnings("unchecked")
@Override
public T methodInvoke(Object object, Method method, Object[] args) {
Socket socket = null;
DataOutputStream dos = null;
DataInputStream dis = null;
try {
socket = new Socket(rmiServerIp, rmiServerPort);
dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(method.toString());
dos.writeUTF(getArgs(args));
dis = new DataInputStream(socket.getInputStream());
String resultString = dis.readUTF();
Type returnType = method.getGenericReturnType();
T result = (T) ArgumentMaker.gson.fromJson(resultString, returnType);
return result;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null && !socket.isClosed()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
};
mecProxy.setMethodInvoker(methdInvoker);
return mecProxy.getProxy(klass);
}
private String getArgs(Object[] args) {
if (args == null || args.length <= 0) {
return "";
}
ArgumentMaker argumentMaker =