目次
具象层 _ 消息抽象的实现
信息的抽象类
实现
JsonMessage
JsonRequest & JsonResponse
消息-差别消息分装实现
实现
Request
RpcRequest
TopicRequest
ServiceRequest
Response
RpcResponse
TopicResponse
ServiceResponse
实现 生产工厂
本篇文章继 BaseMessage 后继续实现,具象层架构图
具象层 _ 消息抽象的实现
信息的抽象类
- Json的信息内容。
- 由JsonRequest和JsonResponse继承来实现差别的功能。
实现
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 下/查询
可以看到上述检测接口
消息-差别消息分装实现
- Json的请求信息。
- JsonRequest实现的派生类:
- RpcRequest:用于远程过程调用请求的实现。
- TopicRequest:可能与特定主题或话题相关的请求实现。
- ServiceRequest:针对服务请求的具体实现。
- Json的回复信息。
- JsonResponse实现的派生类:
- RpcResponse:对应于远程过程调用响应的实现。
- TopicResponse:与特定主题或话题相关响应的实现。
- 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 ¶ms){
- _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)...);
- }
- };
复制代码 下一篇 将遵循 边写边测试,对上面 具象层的 消息类型代码的测试 进行整理
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |