zl程序教程

您现在的位置是:首页 >  后端

当前栏目

基于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编号。