目錄
具象層 _ 消息抽象的實現
信息的抽象類
實現
JsonMessage
JsonRequest & JsonResponse
消息-不同消息分裝實現
實現
Request
RpcRequest
TopicRequest
ServiceRequest
Response
RpcResponse
TopicResponse
ServiceResponse
實現 生產工廠
本篇文章繼 BaseMessage 后繼續實現,具象層架構圖
具象層 _ 消息抽象的實現
信息的抽象類
- JsonMessage
-
- 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 下/查詢
可以看到上述檢測接口
消息-不同消息分裝實現
- JsonRequest
-
- Json的請求信息。
- JsonRequest實現的派生類:
-
RpcRequest
:用于遠程過程調用請求的實現。TopicRequest
:可能與特定主題或話題相關的請求實現。ServiceRequest
:針對服務請求的具體實現。
- JsonResponse
-
- 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 portif (_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)...);}};
下一篇 將遵循 邊寫邊測試,對上面 具象層的 消息類型代碼的測試 進行整理