基于proto的反射做proto和jce两种协议格式转换一个应用实例
2023-06-13 09:11:16 时间
项目背景是,需要对一个结构化消息的后台入口进行收拢,此模块应对客户端的请求分为三类,一、由此模块处理客户端请求,二、由此模块透传一些命令字,三、由此模块透传一些jce请求。针对第三类请求,此模块需要做pb和jce的不同协议格式互转。
在针对此模块第三类请求透传的情况,为了减少后续此模块代码开发,结合pb和jce的协议特性,设计上在pb这边利用pb的反射特性,jce这边,在req和rsp包里面,增加map字段。
jce的demo如下:
struct Req
{
8 optional map<string, string> map_extend; //透传字段
};
struct Rsp
{
5 optional map<string, string> map_extend; //透传字段
};
pb相关的配置(这里只需要增加对应的tag,进而做对应的映射就可以做pb和jce的协议转换做到不改动代码就可以支持):
<ExtTagReq>
10009
</ExtTagReq >
<ExtTagRsp>
10010
</ExtTagRsp>
关于pb到jce的协议转换代码:
//协议字段透传
const ::google::protobuf::Descriptor* descriptor = pbReq.GetDescriptor();
const ::google::protobuf::Reflection* reflection = pbReq.GetReflection();
for (int i = 0; i < g_config.vectorExtTagReq.size(); ++i) {
const ::google::protobuf::FieldDescriptor* fieldDescriptor = descriptor->FindFieldByNumber(g_config.vectorExtTagReq[i]);
if(fieldDescriptor && reflection && (fieldDescriptor->is_required() == true || fieldDescriptor->is_optional() == true)){
if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_INT32){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetInt32(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_INT64){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetInt64(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_UINT32){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetUInt32(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_UINT64){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetUInt64(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetDouble(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_FLOAT){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetFloat(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_BOOL){
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(reflection->GetBool(pbReq, fieldDescriptor));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_ENUM){
const ::google::protobuf::EnumValueDescriptor* pEnumValueDescriptor = reflection->GetEnum(pbReq, fieldDescriptor);
jceReq.map_extend[fieldDescriptor->name()] = wbl::ToString(pEnumValueDescriptor->number());
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_STRING){
jceReq.map_extend[fieldDescriptor->name()] = reflection->GetString(pbReq, fieldDescriptor);
}
}
}
关于jce到pb的协议转换代码:
//协议字段透传
const ::google::protobuf::Descriptor* descriptor = pbRsp.GetDescriptor();
const ::google::protobuf::Reflection* reflection = pbRsp.GetReflection();
for (int i = 0; i < g_config.vectorExtTagRsp.size(); ++i) {
const ::google::protobuf::FieldDescriptor* fieldDescriptor = descriptor->FindFieldByNumber(g_config.vectorExtTagRsp[i]);
if(fieldDescriptor && reflection && (fieldDescriptor->is_required() == true || fieldDescriptor->is_optional() == true)){
if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_INT32){
reflection->SetInt32(&pbRsp, fieldDescriptor, wbl::s2i(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_INT64){
reflection->SetInt64(&pbRsp, fieldDescriptor, wbl::s2l(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_UINT32){
reflection->SetUInt32(&pbRsp, fieldDescriptor, wbl::s2u(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_UINT64){
reflection->SetUInt64(&pbRsp, fieldDescriptor, wbl::s2ul(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE){
reflection->SetDouble(&pbRsp, fieldDescriptor, wbl::strto<double>(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_FLOAT){
reflection->SetFloat(&pbRsp, fieldDescriptor, wbl::strto<float>(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_BOOL){
reflection->SetBool(&pbRsp, fieldDescriptor, wbl::s2i(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_ENUM){
reflection->SetEnumValue(&pbRsp, fieldDescriptor, wbl::s2i(jceRsp.map_extend[fieldDescriptor->name()]));
}else if(fieldDescriptor->cpp_type() == ::google::protobuf::FieldDescriptor::CPPTYPE_STRING){
reflection->SetString(&pbRsp, fieldDescriptor, jceRsp.map_extend[fieldDescriptor->name()]);
}
}
}
以上是应用中的关键地方,在后续需求中,如果需要增加字段,只需要,更新需要转换的pb文件,重新编译到工程里面,在配置里面加上对应的tag编号。
相关文章
- Java 经典实例: Unicode字符和String之间的转换详解编程语言
- SAP 将ITAB内表的数据转换为XML字符串 代码实例详解编程语言
- VB.NET和MySQL的数据库操作实战(vbmysql实例)
- 说明的比较细的php正则学习实例
- Python文件操作技巧(Fileoperation)实例代码分析
- C#操作EXCELDataTable转换的实例代码
- java中字符串与日期的转换实例
- 使用map实现单词转换的实例分析
- Android左右滑出菜单实例分析
- C#图片与二进制转换的简单实例
- javascript中简单的进制转换代码实例
- java中url汉字编码互相转换实例
- JQuery验证jsp页面属性是否为空(实例代码)
- C++基于对话框的程序的框架实例
- JS对象与json字符串格式转换实例
- PHP中UNIX时间戳和日期间的转换与计算实例
- ASP.NET中repeater控件用法实例
- VB读取线程、句柄及写入内存的API代码实例
- yii操作session实例简介