protobuf-c,protobul
墨初 知识笔记 136阅读
Protocal Buffers简称protobuf是谷歌的一项技术用于结构化的数据序列化、反序列化。
官方解释Protocol Buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法它可用于数据通信协议、数据存储等。Protocol Buffers 是一种灵活高效自动化机制的结构数据序列化方法。可类比 XML但是比 XML 更小3 ~ 10倍、更快20 ~ 100倍、更为简单。

你可以定义数据的结构然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构而不破坏由旧数据结构编译的已部署程序。
2、为什么使用protobuf由于 protobuf是跨语言的所以用不同的语言序列化对象后生成一段字节码之后可以其他任何语言反序列化并自用大大方便了跨语言的通讯同时也提高了效率。

需要注意 protobuf生成的是字节码可读性相比略差一点。
创建 FileName.proto文件后缀名称必须是.proto。一般一个文件就代表一个 proto对象。在文件中定义 proto 对象的属性。通过 .proto文件可以生成不同语言的类用于结构化的数据序列化、反序列化。
protobuf官方文档
定义一个 proto 对象的属性基本格式如下
字段标签可选 字段类型 字段名称 字段标识符 字段默认值可选
关于字段编号(标识符)是字段中唯一且必须的以 1开始不能重复不能跳值这个是和编译有关系的。
1、基本数据类型常见基本数据类型
系统默认值
string默认为空字符串byte默认值为空字节bool默认为false数值默认为0enum默认为第一个元素示例如下
syntax proto3;//创建一个 SearchRequest 对象message SearchRequest { string query 1; int32 page_number 2; int32 results_per_page 3;}
3、复杂数据类型 下面通过 Java数据类型来理解定义的 proto属性。并引入 protobuf-java依赖
<!-- --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.19.1</version> </dependency>
3.1 集合List字段 Java String、Integer List 在 protobuf 的定义。
message User{ //list Int repeated int32 intList 1; //list String repeated string strList 2;}
3.2 Map字段 Java String、Integer Map 在 protobuf 的定义。
message User{ // 定义简单的 Map string map<string, int32> intMap 7; // 定义复杂的 Map 对象 map<string, string> stringMap 8;}
3.3 对象字段 Java 对象 List 在 protobuf 的定义。
message User{ //list 对象 repeated Role roleList 6;}
3.4 Map对象值字段 Java 对象 Map 在 protobuf 的定义。
message User{ // 定义复杂的 Map 对象 map<string, MapVauleObject> mapObject 8;}// 定义 Map 的 value 对象message MapVauleObject { string code 1; string name 2;}
3.5 嵌套对象字段 Java 实体类中使用另一个实体类作为字段在 protobuf 的定义。
message User{ // 对象 NickName nickName 4;}// 定义一个新的Name对象message NickName { string nickName 1;}
三、示例实战 1、基本数据类型 1.proto文件
syntax proto3;//生成 proto 文件所在包路径(一般不指定, 生成java类之后人为手动加即可)//package com.example.xxx.model;//生成 proto 文件所在 java包路径(一般不指定因为生成的java_outer_classname类中使用到它会使用全限定名)//option java_package com.example.xxx.model;//生成 proto java文件名(一般指定文件名自定义。如果不指定默认时文件名OuterClass)option java_outer_classname UserProtoBuf;message User { int32 age 1; int64 timestamp 2; bool enabled 3; float height 4; double weight 5; string userName 6; string Full_Address 7; }
生成 Java类。
注意proto没有指定 package xxx; 所以我们将 java类放到目标包下面时记得手动导包。
2测试类
protobuf数据字节数组序列化、反序列化。
public class UserTest { public static void main(String[] args) throws Exception { // 将数据序列化 byte[] byteData getClientPush(); System.out.println(获取到字节数据byteData长度 byteData.length); System.out.println(); /** * 接收数据反序列化将字节数据转化为对象数据。 */ UserProtoBuf.User user UserProtoBuf.User.parseFrom(byteData); System.out.println(user user); System.out.println(UserName user.getUserName()); System.out.println(Timestamp user.getTimestamp()); System.out.println(Height user.getHeight()); } /** * 模拟发送方将数据序列化后发送 * return */ private static byte[] getClientPush() { // 按照定义的数据结构创建一个对象。 UserProtoBuf.User.Builder user UserProtoBuf.User.newBuilder(); user.setAge(18); user.setTimestamp(System.currentTimeMillis()); user.setEnabled(true); //user.setHeight(1.88F); user.setWeight(66.76D); user.setUserName(赵云); user.setFullAddress(王者-打野); /** * 发送数据序列化将对象数据转化为字节数据输出 */ UserProtoBuf.User userBuild user.build(); byte[] bytes userBuild.toByteArray(); return bytes; }}
2、集合/Map类型 1.proto文件
syntax proto3;option java_outer_classname UserListMapProtoBuf;message UserListMap { string userName 1; //list Int repeated int32 intList 2; //list String repeated string strList 3; // 定义Map对象<string, int32> map<string, int32> intMap 4; // 定义Map对象<string, string> map<string, string> stringMap 5;}
2测试类
public class UserListMapTest { public static void main(String[] args) throws Exception { // 将数据序列化 byte[] byteData getClientPush(); System.out.println(获取到字节数据byteData长度 byteData.length); System.out.println(); /** * 接收数据反序列化将字节数据转化为对象数据。 */ UserListMapProtoBuf.UserListMap userListMap UserListMapProtoBuf.UserListMap.parseFrom(byteData); System.out.println(UserListMap userListMap); System.out.println(UserName userListMap.getUserName()); System.out.println(IntList userListMap.getIntListList()); System.out.println(StrList userListMap.getStrListList()); System.out.println(IntMap userListMap.getIntMapMap()); System.out.println(StringMap userListMap.getStringMapMap()); } /** * 模拟发送方将数据序列化后发送 * return */ private static byte[] getClientPush() { // 按照定义的数据结构创建一个对象。 UserListMapProtoBuf.UserListMap.Builder userListMap UserListMapProtoBuf.UserListMap.newBuilder(); userListMap.setUserName(赵云); List<Integer> intList new ArrayList<>(); List<String> strList new ArrayList<>(); intList.add(50); intList.add(51); strList.add(字符串1); strList.add(字符串2); userListMap.addAllIntList(intList); userListMap.addAllStrList(strList); Map<String, String> strMap new HashMap<>(); strMap.put(str-k1, v1); strMap.put(str-k2, v2); userListMap.putIntMap(integer-k1, 60); userListMap.putIntMap(integer-k2, 61); userListMap.putAllStringMap(strMap); /** * 发送数据序列化将对象数据转化为字节数据输出 */ UserListMapProtoBuf.UserListMap userListBuild userListMap.build(); byte[] bytes userListBuild.toByteArray(); return bytes; }}
3、嵌套对象类型 1.proto文件
syntax proto3;option java_outer_classname DemoObjectProtoBuf;message DemoObject { string userName 1; //list InnerObject repeated InnerObject innerObjectList 2; // 定义Map对象<string, InnerObject> map<string, InnerObject> innerObjectMap 3;}// 定义 InnerObject2对象message InnerObject { string name 1; int32 age 2; string code 3;}
2测试类
public class DemoObjectTest { public static void main(String[] args) throws Exception { // 将数据序列化 byte[] byteData getClientPush(); System.out.println(获取到字节数据byteData长度 byteData.length); System.out.println(); /** * 接收数据反序列化将字节数据转化为对象数据。 */ DemoObjectProtoBuf.DemoObject demoObject DemoObjectProtoBuf.DemoObject.parseFrom(byteData); //System.out.println(DemoObject demoObject); System.out.println(UserName demoObject.getUserName()); List<DemoObjectProtoBuf.InnerObject> innerObjectList demoObject.getInnerObjectListList(); for (DemoObjectProtoBuf.InnerObject innerObject : innerObjectList) { System.out.println(innerObject innerObject); System.out.println(Name innerObject.getName()); } Map<String, DemoObjectProtoBuf.InnerObject> innerObjectMap demoObject.getInnerObjectMapMap(); innerObjectMap.forEach((k, v) -> { System.out.println(k k); System.out.println(v v); }); } /** * 模拟发送方将数据序列化后发送 * * return */ private static byte[] getClientPush() { DemoObjectProtoBuf.InnerObject innerObject1 DemoObjectProtoBuf.InnerObject.newBuilder() .setName(in 赵子龙2) .setAge(18) .setCode(code1).build(); DemoObjectProtoBuf.InnerObject innerObject2 DemoObjectProtoBuf.InnerObject.newBuilder() .setName(in 赵子龙2) .setAge(19) .setCode(code2).build(); List<DemoObjectProtoBuf.InnerObject> innerObjList new ArrayList<>(); innerObjList.add(innerObject1); innerObjList.add(innerObject2); Map<String, DemoObjectProtoBuf.InnerObject> innerObjMap new HashMap<>(); innerObjMap.put(k1, innerObject1); innerObjMap.put(k2, innerObject2); // 按照定义的数据结构创建一个对象。 DemoObjectProtoBuf.DemoObject.Builder demoObject DemoObjectProtoBuf.DemoObject.newBuilder(); demoObject.setUserName(赵云); demoObject.addAllInnerObjectList(innerObjList); demoObject.putAllInnerObjectMap(innerObjMap); /** * 发送数据序列化将对象数据转化为字节数据输出 */ DemoObjectProtoBuf.DemoObject demoObjectBuild demoObject.build(); byte[] bytes demoObjectBuild.toByteArray(); return bytes; }}
4、引入外部 proto对象类型 外部 proto文件使用上面的 User.proto。
1.proto文件
syntax proto3;option java_outer_classname Demo2ObjectProtoBuf;// 引入外部的 proto 对象import User.proto;message Demo2Object { string userName 1; // default 张三 //list Int repeated int32 intList 2; //list 对象User为引入的外部 proto文件 repeated User userList 3;}
2测试类
public class DemoObject2Test { public static void main(String[] args) throws Exception { // 将数据序列化 byte[] byteData getClientPush(); System.out.println(获取到字节数据byteData长度 byteData.length); System.out.println(); /** * 接收数据反序列化将字节数据转化为对象数据。 */ Demo2ObjectProtoBuf.Demo2Object demo2Object Demo2ObjectProtoBuf.Demo2Object.parseFrom(byteData); //System.out.println(Demo2Object demo2Object); System.out.println(UserName demo2Object.getUserName()); List<UserProtoBuf.User> userList demo2Object.getUserListList(); for (UserProtoBuf.User user : userList) { System.out.println(user user); } } /** * 模拟发送方将数据序列化后发送 * * return */ private static byte[] getClientPush() { UserProtoBuf.User user UserProtoBuf.User.newBuilder() .setAge(18) .setTimestamp(System.currentTimeMillis()) .setEnabled(true) //.setHeight(1.88F) .setWeight(66.76D) .setUserName(赵云) .setFullAddress(王者-打野).build(); List<UserProtoBuf.User> userList new ArrayList<>(); userList.add(user); userList.add(user); // 按照定义的数据结构创建一个对象。 Demo2ObjectProtoBuf.Demo2Object.Builder demo2Object Demo2ObjectProtoBuf.Demo2Object.newBuilder(); demo2Object.setUserName(赵云); demo2Object.addAllUserList(userList); /** * 发送数据序列化将对象数据转化为字节数据输出 */ Demo2ObjectProtoBuf.Demo2Object demo2ObjectBuild demo2Object.build(); byte[] bytes demo2ObjectBuild.toByteArray(); return bytes; }}
– 求知若饥虚心若愚。