目录
什么是RPC和RMI?
RPC :Remote Procedure Call,远程过程调用
RMI:Remote Method Invocation,远程方法调用
RPC和RMI是有区别的:可以这么理解,RMI就是面向对象的RPC,即,RMI就是用Java实现的RPC
其目的是:利用网络通信,客户端远程调用服务器的方法
其核心思想是:一个端可以通过调用另一个端的方法,实现相关功能。一个端“执行”一个方法,而这个方法的实际执行是在另一端进行的!
个人简单实现思路:
连接方式:TCP 短连接
上图已经很完整的表现了我的实现思路:
建立服务器的时候,首先要进行的就是包扫描,扫描出可以供远程调用的类,把类的方法“注册”,形成一个个的键值对,当客户端远程调用我服务器的方法的时候,根据其发送过来的“键”,找到对应的方法,再结合其发送过来的参数,利用反射机制执行方法,并由服务器将执行结果发送回客户端,客户端收到结果,断开和服务器的连接。实现短连接的一次远程调用。
实现思路很简单,但在完成代码的时候也踩了不少坑。
当然,还有许多问题要结合代码来说明,所以,上代码:
RPC服务器端启动前的准备工作:
1.RpcBeanDefinition
因为需要根据客户端发送过来的“消息”来执行方法,所以就必须要把类,对象,方法“捆绑”在一起
private Class<?> klass;
private Method method;
private Object object;
RpcBeanDefinition() {
}
RpcBeanDefinition(Class<?> klass, Method method, Object object) {
this.klass = klass;
this.method = method;
this.object = object;
}
以上就是该类的一些主要内容,剩下还有get和set方法,就不多说了
2.RpcBeanFactory
我希望每一个Definition都有其唯一的“号码”,客户端只用发送给我服务器他想要调用方法“号码”,我服务器就能通过收到“号码”来找到这个方法,进而执行,多方便。
所以RpcBeanFactory应运而生,他来负责“号码”为键和RpcBeanDefinition为值的键值对集合——rpcBeanMap
private final Map<String, RpcBeanDefinition> rpcBeanMap;
public RpcBeanFactory() {
rpcBeanMap = new HashMap<>();
}
/**
* 往rpcBeanMap中增加键值对,就是注册方法<br>
* 若已经存在该“号码”,则直接返回
* @param rpcBeanId
* @param rpcBeanDefinition
*/
void rpcBeanRegistry(String rpcBeanId, RpcBeanDefinition rpcBeanDefinition) {
RpcBeanDefinition tmp = getRpcBean(rpcBeanId);
if (tmp != null) {
return;
}
rpcBeanMap.put(rpcBeanId, rpcBeanDefinition);
}
/**
* 从rpcBeanMap中获取“值”
* @param rpcBeanId
* @return
*/
RpcBeanDefinition getRpcBean(String rpcBeanId) {
return rpcBeanMap.get(rpcBeanId);
}
3.RpcBeanRegistry
这个类的作用在于“注册”rpcBean,就是来生成“号码” rpcBeanId 和 rpcBeanDefination 的!
这个类的主要方法如下:
/**
* 注册:生成 rpcBeanId 和 rpcBeanDefinition <br>
* 并将其加入到rpcbeanFactory中的map里
* @param rpcBeanFactory
* @param klass
* @param object
*/
private static void doRegist(RpcBeanFactory rpcBeanFactory, Class<?> klass, Object object) {
Method[] methods = klass.getDeclaredMethods();
for (Method method : methods) {
RpcBeanDefinition rpcBeanDefinition = new RpcBeanDefinition(klass, method, object);
String rpcBeanId = Strin