Google Protocol Buffer(protobuf) 使用

Protocol Buffer是google2008年推出的一种数据交换协议,可以使用proto文件将数据序列化或反序列化,google提供了多种语言的实现,每一种实现都包含了相应语言的编译器及库文件,由于Protocol Buffer协议使用二进制格式进行数据传输,所以它比xml和json等协议进行数据交换快。

一、安装protobuf

Mac下通过Homebrew安装protobuf

brew install protobuf

检查protobuf是否安装成功

protoc --version
---
libprotoc 3.6.1
二、Protobuf-Java工具使用
  • 2.1 定义.proto文件

根据protobuf的语法定义需要序列化或反序列化的模型,保存为.proto文件,如本文定义的:TestProtobuf.proto文件:

syntax = "proto3";  // set proto syntax
option java_package = "com.xiaofan.test.protobuf";
option java_outer_classname = "TestCat";
message Cat{
    int64 id = 1;
    string name = 2;
    int32 type = 3;
    repeated string nick = 4;
}
第一行指定使用的是proto3语法,如果不指定,则默认使用proto2语法;
第二行指定生成Java工具所在的包,如果不指定,则采用默认包名;
第三行指定生成Java工具类的名称,如果不指定,则根据.proto文件的名称采用驼峰式命名方式生成;
第四行开始定义protobuf消息类型,即我们需要的数据模型,模型字段的类型是protbuf文件的类型,可参考如下protobuf类型与Java类型的对照表,每个字段都有一个唯一的数字标识符,用于在消息的二进制格式中识别各字段([1,15]的标识符占用一字节,[16,2047]的标识符占2字节)

一个.proto文件可以定义多个消息类型,.proto文件的类型与生成的Java访问类的类型对照如下:

protobuf类型Java类型说明
doubledouble
floatfloat
int32int使用变长编码,编码负数不够高效,如果字段可能有负值,可使用sint32替代
int64long使用变长编码,编码负数不够高效,如果字段可能有负值,可使用sint64替代
uint32int使用变长编码
uint64long使用变长编码
sint32int使用变长编码,有符号的整型,该编码对负值的处理比int32效率高
sint64long使用变长编码,有符号的整型,该编码对负值的处理比int64效率高
fixed32int总是4字节
fixed64long总是8字节
sfixed32int总是4字节
sfixed64long总是8字节
boolboolean
stringString字符串必须是UTF-8编码或者7-bit ASCII编码的文本
bytesByteString可包含任意顺序的字节数据

可以对字段指定修饰符:

修饰符含义
required表示该字段必须要设置。proto3语法中去除了该修饰符
optional表示该字段有0个或1个值。proto3语法去除了该修饰符,如果一个字段不指定修饰符,默认是optional
repeated表示该字段可以重复0次或任意多次,相当于Java中的List
  • 2.2 生成Java工具

通过定义好的.proto文件生成Java工具类,需要机遇.proto文件运行protocal buffer编译器protoc,命令如下:

protoc --proto_path=IMPORT_PATH --java_out=DST_DIR path/to/file.proto

其中: --proto_path可以简写为 -I,实际执行:

protoc --proto_path=/Users/jerry/Desktop/test/protobuf --java_out=/Users/jerry/Desktop/test/protobuf TestProtobuf.proto

or

protoc --I=/Users/jerry/Desktop/test/protobuf --java_out=/Users/jerry/Desktop/test/protobuf TestProtobuf.proto

在proto3语法下执行required修饰符会报如下错误,去除修饰符即可:

TestProtobuf.proto: Required fields are not allowed in proto3.

在proto3语法下执行optional修饰符会报如下错误,去除修饰符即可:

Explicit 'optional' labels are disallowed in the Proto3 syntax. To define 'optional' fields in Proto3, simply remove the 'optional' label, as fields are 'optional' by default.

执行成功后,Java工具会生成在–java_out指定目录下生成根据java_package指定包名相同的文件夹下。

  • 2.3 Java工具使用

生成的Java工具类如下:

// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: TestProtobuf.proto

package com.xiaofan.test.protobuf;

public final class TestCat {
  private TestCat() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  public interface CatOrBuilder extends
	...
  }
...
}

调用示例:

public class TestProtobuf {

    public static void main(String[] args) {
        TestCat.Cat.Builder builder = TestCat.Cat.newBuilder();
        builder.setId(12L);
        builder.setName("Jerry");
        builder.setType(1);
        builder.addNick("brave");
        builder.addNick("handsome");
        builder.addNick("smart");

        TestCat.Cat cat = builder.build();
        System.out.println(cat);

        try {
            TestCat.Cat cat1 = TestCat.Cat.parseFrom(cat.toByteArray());
            System.out.println(cat1);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
    }
}
---
id: 12
name: "Jerry"
type: 1
nick: "brave"
nick: "handsome"
nick: "smart"

id: 12
name: "Jerry"
type: 1
nick: "brave"
nick: "handsome"
nick: "smart"
参考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值