刚进公司,给了个活,了解protocol buffer,应用这个技术给通信做打包和拆包
现在还没拿到公司这块的代码,但是对于工业物联网的项目,报文的消息应该是多样的,用端对端都是同一个消息体显然是不切实际的
那就是接下来的问题了目前想到三个解决方式
两端都维护消息体的protocol生产的java文件,在生产的byte数组前,两外加一些字节负责存放这个类的一些信息,以便接收方可以知道接收的数据属于哪个实体类
这种方式又出现两个解决方式,一是傻瓜式得维护一个类似switch case的方式,通过消息体带的标识,直接转到哪个分支,用什么类去反解成实体类,这个方式最大的缺点就是需要维护这个Switchcase,对修改不友好
第二种方式是,获得类的信息,通过反射的方式,得到类,调用反解方法
说到第二种方式,在网上查到的通过标记类信息反解,用descriptor的方式来做,就有点疑惑,既然我能拿到类的信息,为啥我还要用descriptor来搞反解,为啥不一步到位直接调用这个对象反解
第三种方式就是动态解析
如下就是一个,在用descriptor解析获得一个dynamicMessage后,还需要拼接成一个对象,可能对于json格式的比较合适
protobuf在java应用中通过反射动态创建对象(DynamicMessage)
下方是一个dynamicMessage的应用场景的demo集合
Java Code Examples for com.google.protobuf.DynamicMessage
说一下descriptorSet生成的两种方式 :
相对路径 protoc --descriptor_set_out=cinema.description ./cinema.proto --proto_path=.
绝对路径 protoc --descriptor_set_out=D://cinema1.description D://cinema1.proto --proto_path=D://
贴两个利用生成的descriptor来实现反解的例子
Protobuf动态解析、自描述消息(java版)
Protobuf动态解析在Java中的应用 包含例子程序
这两个例子非常相似,问题在于我的proto定义里有使用其他的message,跑这个demo的时候直接挂了,报找不到那个message的定义
反而采用下方这种,从生成的protojava类里获取的descriptor反解没有报错,这三个例子都有很多短板
做了两次包装和反解,还需要利用反射,性能上损耗应该很大
static void sendAndRead2(byte[] ba) throws InvalidProtocolBufferException { Descriptors.Descriptor descriptor=Ownerpro.Owner.getDescriptor(); DynamicMessage dynamicMessage=DynamicMessage.parseFrom(descriptor,ba); System.out.println(descriptor.getFullName()); System.out.println(descriptor.getIndex()); System.out.println(dynamicMessage.getField(descriptor.findFieldByNumber(1))); //dynamicMessage.getField(descriptor.getIndex()) //dynamicMessage.getField(descriptor.findFieldByNumber()); System.out.println(dynamicMessage.getAllFields()); }
Owner
0
ls
{Owner.name=ls, Owner.phone=33336, Owner.age=56, Owner.houses=[xiaoqu: "hubing"
lou: "15dong"
danyuan: 303
, xiaoqu: "gaoshan"
lou: "8dong"
danyuan: 201
]}
这是打印出的结果,可以看到包含了类的信息,这个要反解成对象的话,还是有点费劲