使用 Socket和动态代理以及反射 实现一个简易的 RPC 调用

使用 Socket、动态代理、反射 实现一个简易的 RPC 调用


我们前面有一篇 socket 的文章,再之前,还有一篇 java动态代理的文章,本文用到了那两篇文章中的知识点,需要的话可以回顾一下。


下面正文开始:

我们的背景是一个名为cuihua-snack(翠花小吃店)的客户端,要调用cuihua-core(翠花核心厨房)的服务端的接口,要求采用RPC的方式调用。
首先,我们创建两个项目cuihua-snack、cuihua-core
在这里插入图片描述

在这里插入图片描述
其中,cuihua-core 包含两个模块(关于 maven的模块化开发 可以再去了解一下),core-api中定义了客户端与服务端共同需要的接口和参数;core-service 则是服务端的主要逻辑。

我们有这样一张系统调用关系示意图。
在这里插入图片描述
① 服务端启动socket服务;
② 客户端开始调用,通过代理的方式调用;
③ 代理中包含 socket 客户端,与服务端建立连接后,将请求接口的对象信息封装后进行序列化。
④ 服务端接收到 socket 请求后,反序列化拿到请求的对象信息。
⑤ 通过反射,调用接口实现类的方法并返回结果。
⑥ 服务端对执行结果序列化并通过socket 返回给客户端。
⑦ 客户端对服务端返回的数据进行反序列化后,输出。
以上七个步骤,就是整个简易RPC的调用过程。


下面我们来看代码:
首先看 core-api 中的代码:
在这里插入图片描述

/*** 上菜服务*/
public interface DishService {String servePickedChineseCabbage(RequestDTO dto);
}
/*** 上菜requestDTO*/
@Data
public class RequestDTO implements Serializable {/*** 菜量*/private String quantityType;//big;medium;small;/*** 是否加辣*/private boolean spicy;/*** 冷热*/private String coldOrHot;//cold/hot
}
/*** RPC Request*/@Data
public class RpcRequest implements Serializable {private String className;private String methodName;private Object[] args;private Class[] types;}

再来看 core-service的代码:
在这里插入图片描述

public class DishServiceImpl implements DishService {public String servePickedChineseCabbage(RequestDTO dto) {System.out.println(dto);return "Please wait a moment! The dish you want will come soon!";}
}
public class RpcService {private DishService service;public RpcService(DishService service){this.service = service;}public void serverRun() throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {ServerSocket serverSocket = new ServerSocket(8000);while(true) {Socket socket = serverSocket.accept();handler(socket);}}private void handler(Socket socket) throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {//读取 socket 传输的数据ObjectInputStream objectinputstrem = new ObjectInputStream(socket.getInputStream());RpcRequest rpcRequest = (RpcRequest) objectinputstrem.readObject();String result = (String) this.invoke(rpcRequest);//将结果写回 socketObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());objectOutputStream.writeObject(result);objectOutputStream.flush();}private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {//通过反射进行服务的调用Class clazz=Class.forName(request.getClassName());//找到目标方法Method method=clazz.getMethod(request.getMethodName(),request.getTypes());return method.invoke(service,request.getArgs());}
}
public class App 
{public static void main( String[] args ) throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {DishService dishService = new DishServiceImpl();RpcService rpcService = new RpcService(dishService);rpcService.serverRun();}
}

最后,我们来看 cuihua-snack的代码:
在这里插入图片描述

public class CuihuaInvocationHandler implements InvocationHandler {private String host;private int port;public CuihuaInvocationHandler(String host,int port){this.host = host;this.port = port;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//开启客户端SocketClient socketClient = new SocketClient(host,port);//请求参数RpcRequest rpcRequest = new RpcRequest();rpcRequest.setArgs(args);rpcRequest.setTypes(method.getParameterTypes());rpcRequest.setClassName(method.getDeclaringClass().getName());rpcRequest.setMethodName(method.getName());//发送Object obj = socketClient.transMessage(rpcRequest);//响应结果return obj;}
}
/*** 代理服务*/
public class ProxyDishService {public  <T> T  getInstance(Class<T> clazz){return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class<?>[]{clazz},new CuihuaInvocationHandler("localhost",8000));}
}
public class SocketClient {private String host;private int port;public SocketClient(String host,int port){this.host = host;this.port = port;}public Socket getSocket() throws IOException {Socket socket = new Socket(host,port);return socket;}public Object transMessage(RpcRequest request){ObjectOutputStream objectOutputStream = null;ObjectInputStream objectInputStream = null;try {Socket socket = getSocket();//将RpcRequest 写入到输出流中,通过socket传递给服务端objectOutputStream = new ObjectOutputStream(socket.getOutputStream());objectOutputStream.writeObject(request);objectOutputStream.flush();//通过输入流,读取服务端通过socket返回的结果objectInputStream = new ObjectInputStream(socket.getInputStream());Object obj = objectInputStream.readObject();return obj;}catch(Exception e){e.printStackTrace();}finally{try {objectInputStream.close();objectOutputStream.close();} catch (IOException e) {e.printStackTrace();}}return null;}
}
public class App 
{public static void main( String[] args ){//调用代理ProxyDishService proxy = new ProxyDishService();RequestDTO dto = new RequestDTO();dto.setColdOrHot("hot");dto.setSpicy(true);dto.setQuantityType("big");String responseStr = proxy.getInstance(DishService.class).servePickedChineseCabbage(dto);System.out.println("响应结果:"+responseStr);}
}

执行 cuihua-core 中 core-service 下的 App 的main方法,启动 ServerSocket;
然后,执行cuihua-snack 中 App 的 main方法,socket客户端发起调用。
服务端打印日志如下:

RequestDTO(quantityType=big, spicy=true, coldOrHot=hot)

客户端打印日志如下:

响应结果:Please wait a moment! The dish you want will come soon!

以上就是 《使用 Socket和动态代理以及反射 实现一个简易的 RPC 调用》的全部内容,感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/382467.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS实现的扫光效果组件

theme: lilsnake 图片和内容如有侵权&#xff0c;及时与我联系~ 详细内容与注释&#xff1a; CSS实现的扫光效果组件 代码 技术栈与框架 Vue3 CSS 扫光效果的原理 扫光效果的原理就是从左到右无限循环的一个位移动画 实现方式 适配文字扫光效果的css .shark-box { …

【devops】gitlab 实现cicd 实践

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

npm 安装报错(已解决)+ 运行 “wue-cli-service”不是内部或外部命令,也不是可运行的程序(已解决)

首先先说一下我这个项目是3年前的一个项目了&#xff0c;中间也是经过了多个人的修改惨咋了布置多少个人的思想&#xff0c;这这道我手里直接npm都安装不上&#xff0c;在网上也查询了多种方法&#xff0c;终于是找到问题所在了 问题1&#xff1a; 先是npm i 报错在下面图片&…

海康视频WEB插件

引入相关依赖 index.html <script src"/video/web-control_1.2.5.min.js"></script> <script src"/video/jquery-1.12.4.min.js" type"text/javascript"></script> <script src"/video/jsencrypt.min.js" …

嵌入式C/C++、FreeRTOS、STM32F407VGT6和TCP:智能家居安防系统的全流程介绍(代码示例)

1. 项目概述 随着物联网技术的快速发展,智能家居安防系统越来越受到人们的重视。本文介绍了一种基于STM32单片机的嵌入式安防中控系统的设计与实现方案。该系统集成了多种传感器,实现了实时监控、报警和远程控制等功能,为用户提供了一个安全、可靠的家居安防解决方案。 1.1 系…

【深度学习】LLaMA-Factory 大模型微调工具, 大模型GLM-4-9B Chat ,微调与部署 (2)

资料&#xff1a; https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md https://www.53ai.com/news/qianyanjishu/2015.html 代码拉取&#xff1a; git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factorybuild镜像和执行镜像&#xff1a; …

“机器说人话”-AI 时代的物联网

万物互联的物联网愿景已经提了许多年了&#xff0c;但是实际效果并不理想&#xff0c;除了某些厂商自己的产品生态中的产品实现了互联之外&#xff0c;就连手机控制空调&#xff0c;电视机和调光灯都没有实现。感觉小米做的好一点&#xff0c;而华为的鸿蒙的全场景&#xff0c;…

【云原生】Kubernetes 中的 PV 和 PVC 介绍、原理、用法及实战案例分析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

nginx漏洞修复 ngx_http_mp4_module漏洞(CVE-2022-41742)【低可信】 nginx版本升级

风险描述&#xff1a; Nginx 是一款轻量级的Web服务器、反向代理服务器。 Nginx 的受影响版本中的ngx _http_mp4_module模块存在内存越界写入漏洞&#xff0c;当在配置中使用 mp4 directive时&#xff0c;攻击者可利用此漏洞使用使用ngx_http_mp4_module模块处理特制的音频或视…

Hive分布式SQL计算平台

Hive分布式SQL计算平台 一、Hive 概述二、Hive架构三、Hive客户端 1、Hive有哪些客户端可以使用2、Hive第三方客户端 四、Hive使用语法 1、数据库操作2、内部表&#xff0c;外部表3、数据的导入与导出4、分区表5、分桶表6、复杂类型操作7、数据抽样8、Virtual Columns 虚拟列9…

springboot 项目整合 AI (文心一言)

百度智能云网址&#xff1a;https://cloud.baidu.com/?fromconsole 注册——个人认证——登录成功 第一步&#xff1a;点击千帆大模型平台 ​ 第二步&#xff1a;点击应用接入——创建应用 ​ 第三步&#xff1a;点击接口文档——API列表——可以点击指定模型进行查看调…

Spring Boot集成Activity7实现简单的审批流

由于客户对于系统里的一些新增数据&#xff0c;例如照片墙、照片等&#xff0c;想实现上级逐级审批通过才可见的效果&#xff0c;于是引入了Acitivity7工作流技术来实现&#xff0c;本文是对实现过程的介绍讲解&#xff0c;由于我是中途交接前同事的这块需求&#xff0c;所以具…

DolphinDB Web 端权限管理:可视化操作指南

在现代数据库管理中&#xff0c;高效和直观的权限管理对于用户的数据安全是至关重要的。过去 DolphinDB 用户需要依赖系统脚本来管理用户和权限&#xff0c;这对于缺乏技术背景的管理员来说既复杂又容易出错。 为了提升用户体验和操作效率&#xff0c;DolphinDB 目前在 Web 上…

【ACM出版】2024集成电路设计与集成系统国际研讨会(ICDIS2024)

会议日期&#xff1a;2024年11月22-24日 会议地点&#xff1a;中国-厦门 会议官网&#xff1a;https://www.iaast.cn/meet/home/Bx122dOo 【大会主席】 Sri Niwas Singh&#xff0c;印度信息技术与管理研究所 【主讲嘉宾】 【论文出版与检索】 大会即日起围绕主题征集会…

Beyond Compare 5 for Mac/Win:高效文件同步与对比的专业工具

Beyond Compare 5是一款专为Mac和Windows用户设计的强大文件同步与对比软件&#xff0c;由Scooter Software精心打造。它凭借卓越的功能和易用性&#xff0c;在软件开发、系统管理和数据同步领域广受好评。 这款软件支持多种文件类型的对比&#xff0c;包括文件夹、文本文件、…

(7) cmake 编译C++程序(二)

文章目录 概要整体代码结构整体代码小结 概要 在ubuntu下&#xff0c;通过cmake编译一个稍微复杂的管理程序 整体代码结构 整体代码 boss.cpp #include "boss.h"Boss::Boss(int id, string name, int dId) {this->Id id;this->Name name;this->DeptId …

开发环境搭建

1、Ubuntu 系统设置 root 用户密码 新安装的ubuntu没有设置 root 用户密码,打开终端,输入 sudo passwd root 执行命令后依次输入密码 2、虚拟机设置网络适配器 3、Ubuntu 系统下搭建 FTP 服务器 sudo apt-get update sudo apt-get install vsftpd sudo apt-get install vim…

如何切换网络IP地址?IP切换的应用与方法

随着互联网的发展和普及&#xff0c;我们日常生活中的各种操作和通讯越来越依赖互联网。互联网上存在的一些问题和限制使得更换IP地址成为必要的步骤。下面我们将探讨在互联网业务中&#xff0c;需要更换IP地址的原因与方法。 一、IP轮换的应用 解决访问限制&#xff1a;解决访…

HTTPServer改进思路1

Nginx源码思考项目改进 架构模式 事件驱动架构(EDA&#xff09;用于处理大量并发连接和IO操作 优点&#xff1a;高效处理大量并发请求&#xff0c;减少线程切换和阻塞调用技术实现&#xff1a;直接使用EPOLL&#xff0c;参考Node.js的http服务器 网络通信 协议&#xff1a;HTT…

Spark_Oracle_II_Spark高效处理Oracle时间数据:通过JDBC桥接大数据与数据库的分析之旅

接前文背景&#xff0c; 当需要从关系型数据库&#xff08;如Oracle&#xff09;中读取数据时&#xff0c;Spark提供了JDBC连接功能&#xff0c;允许我们轻松地将数据从Oracle等数据库导入到Spark DataFrame中。然而&#xff0c;在处理时间字段时&#xff0c;可能会遇到一些挑战…