[实现Rpc] 消息抽象层的具体实现

目录

具象层 _ 消息抽象的实现

信息的抽象类

实现

JsonMessage

JsonRequest & JsonResponse

消息-不同消息分装实现

实现

Request

RpcRequest

TopicRequest

ServiceRequest

Response

RpcResponse

TopicResponse

ServiceResponse

实现 生产工厂


本篇文章继 BaseMessage 后继续实现,具象层架构图

具象层 _ 消息抽象的实现

信息的抽象类
  1. JsonMessage
    • Json的信息内容。
    • JsonRequestJsonResponse继承来实现不同的功能。

实现

JsonMessage

 typedef std::pair<std::string,int> Address;
    class JsonMessage:public BaseMessage{
        //继承
        public:
        using ptr=std::shared_ptr<JsonMessage>;
        virtual std::string serialize() override{
            //!!!!override 继承重写的强校验
            std::string body;
            bool ret=JSON::serialize(_body,body);
            if(ret==false){
                return std::string();
                //序列化失败
            }
            return body;
        }
        virtual bool unserialize(const std::string &msg) override{
            return JSON::unserialize(msg,_body);
        }

        protected:
            Json::Value _body;
    }

⭕ 前文回顾

1.over ride 继承重写的强校验

[C++#28][多态] 两个条件 | 虚函数表 | 抽象类 | override 和 final | 重载 重写 重定义

2.

继承类不能用 private,要用 protected


JsonRequest & JsonResponse

//2.
     class JsonRequest:public JsonMessage{
        public:
            using ptr=std::shared_ptr<JsonRequest>;
     };

     class JsonResponse:public JsonMessage{
        public:
            using ptr=std::shared_ptr<JsonResponse>;
            virtual bool check() override{
                //在响应中,大部分的响应都 只有响应状态码
                //only chaeck 状态码是否存在,类型 是否正确
                if(_body[KEY_RCODE].isNull()==true){
                    ELOG("响应中 没有响应状态码!");
                    return false;
                }
                if(_body[KEY_RCODE].isIntegral()==false){
                    ELOG("响应状态码 类型错误!");
                    return false;
                }
                return true;
            }

            virtual RCode rcode(){
                return (RCode)_body[KEY_RCODE].asInt();
                //将body中的提示码 整型化
            }
            virtual void setRCode(RCode rcode){
                _body[KEY_RCODE]=(int)rcode;
            }
     };

1.通过继承 提高代码复用,去冗余

2. 使用 vi 查询 json 中接口

vi /usr/include/jsoncpp/json/value.h

esc 下/查询

可以看到上述检测接口


消息-不同消息分装实现

  1. JsonRequest
    • Json的请求信息。
    • JsonRequest实现的派生类
    1. RpcRequest:用于远程过程调用请求的实现。
    2. TopicRequest:可能与特定主题或话题相关的请求实现。
    3. ServiceRequest:针对服务请求的具体实现。
  1. JsonResponse
    • Json的回复信息。
    • JsonResponse实现的派生类
    1. RpcResponse:对应于远程过程调用响应的实现。
    2. TopicResponse:与特定主题或话题相关响应的实现。
    3. ServiceResponse:服务于具体服务响应的实现。

实现

Request

RpcRequest
class RpcRequest:public JsonRequest{
    public:
        using ptr=std::shared_ptr<RpcRequest>;
        virtual bool check() override{
            //重写 check 函数
            //rpc 请求中,包含 请求方法名称-字符串,参数字段-对象
            if(_body[KEY_METHOD].isNull()==true||
            _body[KEY_METHOD].isString()==false){
                ELOG("RPC请求中 没有方法名称 或者 方法名称 类型错误");
                return false;
            }

            if(_body[KEY_PARAMS].isNull()==true||
            _body[KEY_PARAMS].isObject()==false
            ){
                ELOG("RPC请求中 没有 参数信息或 参数信息类型错误!");
                return false;
            }
            return true;
        }
        std::string method(){
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method_name){
            _body[KEY_METHOD]=method_name;
        }

        Json::Value params(){
            return _body[KEY_PARAMS];
        }
        void setParams(const Json::Value &params){
            _body[KEY_PARAMS]=params;
        }
};
TopicRequest
    class TopicRequest : public JsonRequest {
        public:
            using ptr = std::shared_ptr<TopicRequest>;
            virtual bool check() override {
                //rpc请求中,包含请求方法名称-字符串,参数字段-对象
                if (_body[KEY_TOPIC_KEY].isNull() == true ||
                    _body[KEY_TOPIC_KEY].isString() == false) {
                    ELOG("主题请求中没有主题名称或主题名称类型错误!");
                    return false;
                }
                if (_body[KEY_OPTYPE].isNull() == true ||
                    _body[KEY_OPTYPE].isIntegral() == false) {
                    ELOG("主题请求中没有操作类型或操作类型的类型错误!");
                    return false;
                }
                if (_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH &&
                    (_body[KEY_TOPIC_MSG].isNull() == true ||
                    _body[KEY_TOPIC_MSG].isString() == false)) {
                    ELOG("主题消息发布请求中没有消息内容字段或消息内容类型错误!");
                    return false;
                }
                return true;
            }
            
            std::string topicKey() {
                return _body[KEY_TOPIC_KEY].asString();
            }
            void setTopicKey(const std::string &key) {
                _body[KEY_TOPIC_KEY] = key;
            }
            TopicOptype optype() {
                return (TopicOptype)_body[KEY_OPTYPE].asInt();
            }
            void setOptype(TopicOptype optype) {
                _body[KEY_OPTYPE] = (int)optype;
            }
            std::string topicMsg() {
                return _body[KEY_TOPIC_MSG].asString();
            }
            void setTopicMsg(const std::string &msg) {
                _body[KEY_TOPIC_MSG] = msg;
            }

    };
ServiceRequest
class ServiceRequest : public JsonRequest {
        public:
            using ptr = std::shared_ptr<ServiceRequest>;
            virtual bool check() override {
                //rpc请求中,包含请求方法名称-字符串,参数字段-对象
                if (_body[KEY_METHOD].isNull() == true ||
                    _body[KEY_METHOD].isString() == false) {
                    ELOG("RPC请求中没有方法名称或方法名称类型错误!");
                    return false;
                }
                if (_body[KEY_OPTYPE].isNull() == true ||
                    _body[KEY_OPTYPE].isIntegral() == false) {
                    ELOG("服务请求中没有操作类型或操作类型的类型错误!");
                    return false;
                }

        //!!!!!!!!!! 服务发现  不需要提供主机 ip port
                if (_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                    (_body[KEY_HOST].isNull() == true ||
                    _body[KEY_HOST].isObject() == false ||
                    _body[KEY_HOST][KEY_HOST_IP].isNull() == true ||
                    _body[KEY_HOST][KEY_HOST_IP].isString() == false ||
                    _body[KEY_HOST][KEY_HOST_PORT].isNull() == true ||
                    _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false)) {
                    ELOG("服务请求中主机地址信息错误!");
                    return false;
                }
                return true;
            }


            std::string method() {
                return _body[KEY_METHOD].asString();
            }

            //引用传参
            void setMethod(const std::string &method_name) {
                _body[KEY_METHOD] = method_name;
            }

            ServiceOptype optype(){
                return (ServiceOptype)_body[KEY_OPTYPE].asInt();
            }
//枚举类型较小 前面不加&也行
            void setOptype(ServiceOptype optype){
                _body[KEY_OPTYPE]=(int)optype;
            }

            Address host(){
                Address addr;
    //!!!!!!!!!!!!!!!
    //粗心写成 _body[KEY_HOST_IP] 报错 排查了快半小时qwq      
                addr.first=_body[KEY_HOST][KEY_HOST_IP].asString();
                addr.second=_body[KEY_HOST][KEY_HOST_PORT].asInt();
                return addr;
            }

            void setHost(const Address &host){
                Json::Value val;
                val[KEY_HOST_IP]=host.first;
                val[KEY_HOST_PORT]=host.second;
                _body[KEY_HOST]=val;
            }
    };

1.询问中的服务发现

2.

3.

⭕为什么 要 这样设计?

issues 回复:

这是向外提供的两个不i同功能的接口呀

  • 一个是用于获取body中的数据的
  • 一个是用户设置body内容的....

Response

RpcResponse
class RpcResponse:public JsonResponse{
    public:
        using ptr=std::shared_ptr<RpcResponse>;
        virtual bool check() override{
            if(_body[KEY_RCODE].isNull()==true||
               _body[KEY_RCODE].isIntegral()==false )
            {
                ELOG("响应中没有 响应状态码,或者 状态码 类型错误");
                return false;
            }

           if (_body[KEY_RESULT].isNull() == true) {
                    ELOG("响应中没有Rpc调用结果,或结果类型错误!");
                    return false;
                }
                return true;
            }
            Json::Value result() {
                return _body[KEY_RESULT];
            }
            void setResult(const Json::Value &result) {
                _body[KEY_RESULT] = result;
            }
    };
TopicResponse
class TopicResponse : public JsonResponse {
        public:
            using ptr = std::shared_ptr<TopicResponse>;
    };
ServiceResponse

class ServiceResponse : public JsonResponse {
        public:
            using ptr = std::shared_ptr<ServiceResponse>;
            virtual bool check() override {
                if (_body[KEY_RCODE].isNull() == true ||
                    _body[KEY_RCODE].isIntegral() == false) {
                    ELOG("响应中没有响应状态码,或状态码类型错误!");
                    return false;
                }
                if (_body[KEY_OPTYPE].isNull() == true ||
                    _body[KEY_OPTYPE].isIntegral() == false) {
                    ELOG("响应中没有操作类型,或操作类型的类型错误!");
                    return false;
                }

//!!!!!!!!!!!!!!!对服务发现部分 进行处理
                if (_body[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                   (_body[KEY_METHOD].isNull() == true ||
                    _body[KEY_METHOD].isString() == false ||
                    _body[KEY_HOST].isNull() == true ||
                    _body[KEY_HOST].isArray() == false)) {
                    ELOG("服务发现响应中响应信息字段错误!");
                    return false;
                }
                return true;
            }
            ServiceOptype optype() {
                return (ServiceOptype)_body[KEY_OPTYPE].asInt();
            }
            void setOptype(ServiceOptype optype) {
                _body[KEY_OPTYPE] = (int)optype;
            }


            std::string method() {
                return _body[KEY_METHOD].asString();
            }
            void setMethod(const std::string &method) {
                _body[KEY_METHOD] = method;
            }

// !!!!!!!!!!!!!!!!!!!!!!!!!
            void setHost(std::vector<Address> addrs) {
                for (auto &addr : addrs) {
                    Json::Value val;
                    val[KEY_HOST_IP] = addr.first;
                    val[KEY_HOST_PORT] = addr.second;
                    _body[KEY_HOST].append(val);
                }
            }
            std::vector<Address> hosts() {
                std::vector<Address> addrs;
                int sz = _body[KEY_HOST].size();
                for (int i = 0; i < sz; i++) {
                    Address addr;
                    addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                    addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                    addrs.push_back(addr);
                }
                return addrs;
            }
    };


实现 生产工厂

 //实现一个消息对象的生产工厂
    class MessageFactory {
        public:
            static BaseMessage::ptr create(MType mtype) {
                switch(mtype) {
                    case MType::REQ_RPC : return std::make_shared<RpcRequest>();
                    case MType::RSP_RPC : return std::make_shared<RpcResponse>();
                    case MType::REQ_TOPIC : return std::make_shared<TopicRequest>();
                    case MType::RSP_TOPIC : return std::make_shared<TopicResponse>();
                    case MType::REQ_SERVICE : return std::make_shared<ServiceRequest>();
                    case MType::RSP_SERVICE : return std::make_shared<ServiceResponse>();
                }
                return BaseMessage::ptr();
            }
            
            template<typename T, typename ...Args>
            static std::shared_ptr<T> create(Args&& ...args) {
                return std::make_shared<T>(std::forward(args)...);
            }
    };

下一篇 将遵循 边写边测试,对上面 具象层的 消息类型代码的测试 进行整理

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《A++ 敏捷开发》- 16 评审与结对编程

客户&#xff1a;我们的客户以银行为主&#xff0c;他们很注重质量&#xff0c;所以一直很注重评审。他们对需求评审、代码走查等也很赞同&#xff0c;也能找到缺陷&#xff0c;对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。 我&#xff1a;你听说过敏捷的结对…

PHP房屋出租出售高效预约系统小程序源码

&#x1f3e0; 房屋出租出售高效预约系统 —— 您的智能找房新选择 &#x1f4a1; 这是一款集智慧与匠心于一体的房屋出租出售预约系统&#xff0c;它巧妙地融合了ThinkPHP与Uniapp两大先进框架&#xff0c;精心打造而成。无论是小程序、H5网页&#xff0c;还是APP端&#xff…

给老系统做个安全检查——Burp SqlMap扫描注入漏洞

背景 在AI技术突飞猛进的今天&#xff0c;类似Cursor之类的工具已经能写出堪比大部分程序员水平的代码了。然而&#xff0c;在我们的代码世界里&#xff0c;仍然有不少"老骥伏枥"的系统在兢兢业业地发光发热。这些祖传系统的代码可能早已过时&#xff0c;架构可能岌…

Repeated Sequence

记suma[1]a[2]a[3]...a[n]。 该序列以a[1]&#xff0c;a[2]&#xff0c;a[3]....a[n]为循环节&#xff0c;明显的&#xff0c;问题可转化为:s%sum是否为该序列的某个连续子序列和。 断环为链。将a复制一份。 枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O&#x…

【DeepSeek】Mac m1电脑部署DeepSeek

一、电脑配置 个人电脑配置 二、安装ollama 简介&#xff1a;Ollama 是一个强大的开源框架&#xff0c;是一个为本地运行大型语言模型而设计的工具&#xff0c;它帮助用户快速在本地运行大模型&#xff0c;通过简单的安装指令&#xff0c;可以让用户执行一条命令就在本地运…

dockerfile 使用环境变量

ARG&#xff1a; Defining build-time variables ARG指令允许您定义在构建阶段可以访问但在构建映像之后不可用的变量。例如&#xff0c;我们将使用这个Dockerfile来构建一个映像&#xff0c;我们在构建过程中使用ARG指令指定的变量。 FROM ubuntu:latest ARG THEARG"fo…

基于WebGIS技术的校园地图导航系统架构与核心功能设计

本文专为IT技术人员、地理信息系统&#xff08;GIS&#xff09;开发者、智慧校园解决方案架构师及相关领域的专业人士撰写。本文提出了一套基于WebGIS技术的校园地图导航系统构建与优化方案&#xff0c;旨在为用户提供高效、智能、个性化的导航体验。如需获取校园地图导航系统技…

idea连接gitee(使用idea远程兼容gitee)

文章目录 先登录你的gitee拿到你的邮箱找到idea的设置选择密码方式登录填写你的邮箱和密码登录成功 先登录你的gitee拿到你的邮箱 具体位置在gitee–>设置–>邮箱管理 找到idea的设置 选择密码方式登录 填写你的邮箱和密码 登录成功

【从0做项目】Java音缘心动(3)———加密算法 MD5 BCrypt

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 零&#xff1a;项目结果展示 一&#xff1a;音乐播放器Web网页介绍 二&#xff1a;加密算法介绍 1&…

新数据结构(12)——代理

什么是代理 在进行操作时有时不希望用户直接接触到目标&#xff0c;这时需要使用代理让用户间接接触到目标 给目标对象提供一个代理对象&#xff0c;并且由代理对象控制着对目标对象的引用 图解&#xff1a; 代理的目的 控制访问&#xff1a;通过代理对象的方式间接的访问目…

基于大语言模型的推荐系统(1)

推荐系统&#xff08;recommendation system&#xff09;非常重要。事实上&#xff0c;搜索引擎&#xff0c;电子商务&#xff0c;视频&#xff0c;音乐平台&#xff0c;社交网络等等&#xff0c;几乎所有互联网应用的核心就是向用户推荐内容&#xff0c;商品&#xff0c;电影&…

学习threejs,使用MeshBasicMaterial基本网格材质

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshBasicMaterial 二…

Selenium实战案例2:东方财富网股吧评论爬取

上一篇文章&#xff0c;我们使用Selenium完成了网页内文件的自动下载,本文我们将使用Selenium来爬取东方财富网股吧内笔记的评论数据。 网页内容分析 网页内容的分析是web自动化中的关键一步。通过分析网页结构&#xff0c;我们可以确定需要抓取的数据位置以及操作元素的方式。…

零基础学python--------第三节:Python的流程控制语法

Python&#xff0c;浮点数 11.345(单&#xff1a;4个字节&#xff0c; 双&#xff1a;8个字节) 。 十进制的数字25 ---> 11001 讲一个小数转化为二进制&#xff1a; 不断的乘以2 。取整数部分。 十进制的0.625 ----> 二进制&#xff1a; 0&#xff0c; 101 。 0.3 ---…

MKS SERVO42E57E 闭环步进电机_系列10 STM32_脉冲和串口例程

文章目录 第1部分 产品介绍第2部分 相关资料下载2.1 MKS E系列闭环步进驱动资料2.2 源代码下载2.3 上位机下载 第3部分 脉冲控制电机运行示例第4部分 读取参数示例4.1 读取电机实时位置4.2 读取电机实时转速4.3 读取电机输入脉冲数4.4 读取电机位置误差4.5 读取电机IO端口状态 …

小米路由器 AX3000T 降级后无法正常使用,解决办法

问题描述 买了个 AX3000T 路由器&#xff0c;想安装 OpenWRT 或者 安装 Clash 使用&#xff0c;看教程说是需要降级到 v1.0.47 版本。 结果刷机之后路由器无法打开了&#xff0c;一直黄灯亮&#xff0c;中间灭一下&#xff0c;又是黄灯长亮&#xff0c;没有 WIFI 没有连接。以…

强化学习-GAE方法

2016-ICLR-HIGH-DIMENSIONAL CONTINUOUS CONTROL USING GENERALIZED ADVANTAGE ESTIMATION 解决问题 强化学习的目标为最大化策略的预期总回报&#xff0c;其中一个主要困难为 行为对reward的影响存在一个长时间的延迟&#xff08;credit assignment problem&#xff09;。价…

写大论文的word版本格式整理,实现自动生成目录、参考文献序号、公式序号、图表序号

前情提要&#xff1a;最近开始写大论文&#xff0c;发现由于内容很多导致用老方法一个一个改的话超级麻烦&#xff0c;需要批量自动化处理&#xff0c;尤其是序号&#xff0c;在不断有增添删减的情况时序号手动调整很慢也容易出错&#xff0c;所以搞一个格式总结&#xff0c;记…

清华大学deepseek教程第四版 DeepSeek+DeepResearch 让科研像聊天一样简单(附下载)

deepseek使用教程系列 DeepSeekDeepResearch 让科研像聊天一样简单(附下载) https://pan.baidu.com/s/1VMgRmCSEzNvhLZQc8mu6iQ?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/f3d4511b790a

面阵工业相机提高餐饮业生产效率

餐饮行业是一个快节奏、高要求的领域&#xff0c;该领域对生产过程中每一个阶段的效率和准确性都有很高的要求。在食品加工、包装、质量控制和库存管理等不同生产阶段实现生产效率的优化是取得成功的关键步骤。面阵工业相机能够一次性捕捉对象的二维区域图像&#xff0c;并支持…