Google Protobuf编解码(序列化/反序列化)框架
Google Protobuf编解码(序列化/反序列化)框架
兴趣使然的程序员 发表于1年前
Google Protobuf编解码(序列化/反序列化)框架
  • 发表于 1年前
  • 阅读 64
  • 收藏 0
  • 点赞 0
  • 评论 0

【腾讯云】新注册用户域名抢购1元起>>>   

编码/解码在Java中又称序列化/反序列化,Java本身的序列化反序列化技术生成的二进制码流太大,且转化效率低下,一般不适用于远程跨节点调用的编码框架。

Protobuf全称Protocol Buffers,由谷歌开源而来,特点如下:

  1. 码流小、效率高
  2. 语言平台无关,不只Java可以用,C++、python亦可
  3. 使用数据描述文件,可自动生成代码
  4. 和Facebook Thirft对比,Protobuf并不需要完全在开始就完全定义好全部结构,而可以在后期extends之前的结构,并且仍然可以读取之前结构编码的信息

使用步骤:

  1. 编写.proto类定义文件
  2. 通过提供的编译器产生对应的Java类
  3. 使用提供的API读写信息

1、编写.proto类定义文件

package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

文件说明:

  1. package用于区分同名文件,在java_package缺省时,就是产生的bean的包
  2. java_outer_classname指定包含文件中定义的所有类的类,如果缺省,会自动将.proto文件名设为类名
  3. message定义一个类,message中可以包含message
  4. 每个属性后面的 =1、=2等数字是在二进制化数据时,属性的“唯一标识”,在每个message中独立编号

支持的修饰符:

  1. required:标识必须被提供的字段,如果required字段的值没有被提供,编码解码时都会跑出异常;
  2. optional:标识可以提供或不提供的字段,如果不提供,则返回默认值。默认值和java中相似,但是“子message”的字段会全部为空。默认值也可以用[default = value]进行设置;
  3. repeated:标识ArrayList
  4. 每个属性后面的 =1、=2等数字,注意0-15比之后的数字再序列化时少一个字节,固0-15一般用在required和repeated字段上

支持的数据类型:boolint32floatdoublestringenum 

.proto Type Notes C++ Type Java Type Python Type Go Type
double   double double float *float64
float   float float float *float32
int32 虽然可以有负数,但是效率不高 int32 int int *int32
int64 虽然可以有负数,但是效率不高 int64 long int/long[3] *int64
uint32 无符号整数,只能是正数 uint32 int int/long[3] *uint32
uint64 无符号整数,只能是正数 uint64 long int/long[3] *uint64
sint32 有符号整数,表示负数的效率更高 int32 int int *int32
sint64 有符号整数,表示负数的效率更高 int64 long int/long[3] *int64
fixed32 永远占据4个字节,如果超过256的话,效率更高 uint32 int int *uint32
fixed64 永远占据8个字节,如果超过256的话,效率更高 uint64 long int/long[3] *uint64
sfixed32 永远占据4个字节 int32 int int *int32
sfixed64 永远占据8个字节 int64 long int/long[3] *int64
bool   bool boolean bool *bool
string 字符串必须是UTF-8或者7-bit ASCII。 string String str/unicode *string
bytes   string ByteString str []byte

备注:

[3] Python3中不再有int和long之分,而只有不限长度的整型int。

2、通过提供的编译器产生对应的Java类

2.1、将protoc.exe和对应的.proto文件放到项目所在的java文件夹下

protoc.exe --java_out=.\ .\Request.proto

就可以在上面的proto文件中的java_package描述的位置产生指定的文件

3、使用提供的API读写信息

public class TestSubscribeReqProto {
    /**
     * 1、构建对象
     * @return
     */
    public static SubscribeReqProto.SubscribeReq createSubscribeReq(){
        SubscribeReqProto.SubscribeReq.Builder builder =
                SubscribeReqProto.SubscribeReq.newBuilder();
        builder.setSubReqID(1);
        builder.setUserName("caizhijie");
        builder.setProductName("Yellow Book");
        List<String> address = new ArrayList<>();
        address.add("NanJing YuHuaTai");
        address.add("BeiJing ZhiJinCheng");
        address.add("ShenZhen HongShuLin");
        builder.addAllAddress(address);
        return builder.build();
    }

    /**
     * 2、编码
     * @param req
     * @return
     */
    public static byte[] encode(SubscribeReqProto.SubscribeReq req){
        return req.toByteArray();
    }

    /**
     * 3、解码
     * @param body
     * @return
     * @throws InvalidProtocolBufferException
     */
    public static SubscribeReqProto.SubscribeReq decode(byte[] body) throws InvalidProtocolBufferException {
        return SubscribeReqProto.SubscribeReq.parseFrom(body);
    }

    public static void main(String[] args) throws InvalidProtocolBufferException {
        SubscribeReqProto.SubscribeReq req = createSubscribeReq();
        System.out.println("Before encode : "+req.toString());
        SubscribeReqProto.SubscribeReq req2 = decode(encode(req));
        System.out.println("After encode : "+req2.toString());
        System.out.println("Assert equal : -->" + req2.equals(req));
    }
}

 

标签: Java Google ProtoBuf
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 20
博文 108
码字总数 86458
×
兴趣使然的程序员
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: