欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

protobuf-c,protobul

墨初 知识笔记 136阅读
一、protobuf简介 1、什么是 protobuf

Protocal Buffers简称protobuf是谷歌的一项技术用于结构化的数据序列化、反序列化。

官方解释Protocol Buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法它可用于数据通信协议、数据存储等。Protocol Buffers 是一种灵活高效自动化机制的结构数据序列化方法。可类比 XML但是比 XML 更小3 ~ 10倍、更快20 ~ 100倍、更为简单。

你可以定义数据的结构然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构而不破坏由旧数据结构编译的已部署程序。

2、为什么使用protobuf

由于 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;    }}

– 求知若饥虚心若愚。

标签:
声明:无特别说明,转载请标明本文来源!