一文读懂Protobuf序列化协议的使用

Protobuf是谷歌推出的一款平台无关的序列化协议,相比传统的序列化方式,Protobuf体积更小,更灵活,能有效提高传输效率,减少数据传输过程中占用的带宽。简单来说,Protobuf有以下特点:

语言无关、平台无关。Protobuf支持Java、C++、Python等多种语言,多个平台
高效。比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单
扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程序

本文以Animal实体类为例,感受protobuf的特点;

public class Animal implements Serializable {

    private Long id;
    private String name;
    private List<String> actions;
    
	/**省略get、set方法**/
}

一、使用Protobuf

创建AnimalProto.proto,定义的数据类型如下:

package com.keduw.protobuf;

message Animal{
    //id
    required int64 id = 1;
    //name
    optional string name = 2;
    //actions
    repeated string actions = 3;
}

Protobuf定义了它自己的语法规则。package定义我们最后生成Java代码所属的包,required表示该字段是必填的,optional表示该字段是可选的,而repeated则标明该字段是可连续的,对应到Java中则表示一个集合,通过定义字段的顺序方便Protobuf对字段的反序列化。具体对应的数据类型可以参考如下:
在这里插入图片描述
编写好AnimalProto.proto,可以通过官网提供的protoc.exe生成对应的Java代码(如果找不到可在文章末尾下载)。

二、序列化和反序列化

前面通过工具生成的代码(AnimalProto)已经帮我们封装好了序列化和反序列化的方法,我们只需要调用对应方法即可。

引入Protobuf的依赖

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>2.4.1</version>
</dependency>

序列化:

/**
 * 调用对象构造好的Builder,完成属性赋值和序列化操作
 * @return
 */
public static byte[] protobufSerializer(){
    AnimalProto.Animal.Builder builder = AnimalProto.Animal.newBuilder();
    builder.setId(1L);
    builder.setName("小猪");
    List<String> actions = new ArrayList<>();
    actions.add("eat");
    actions.add("run");
    builder.addAllActions(actions);
    return builder.build().toByteArray();
}

反序列化:

/**
 * 通过调用parseFrom则完成反序列化
 * @param bytes
 * @return
 * @throws InvalidProtocolBufferException
 */
public static Animal deserialize(byte[] bytes) throws Exception {
    AnimalProto.Animal pAnimal = AnimalProto.Animal.parseFrom(bytes);
    Animal animal = new Animal();
    animal.setId(pAnimal.getId());
    animal.setName(pAnimal.getName());
    animal.setActions(pAnimal.getActionsList());
    return animal;
}

测试:

public static void main(String[] args) throws Exception {
    byte[] bytes = serializer();
    Animal animal = deserialize(bytes);
    System.out.println(animal);
}

可以看到是能正常序列化和反序列化的。在这里插入图片描述

三、性能对比

另外,我在这里还单独对比了Java原生序列化、jackson和Protobuf序列化对同一个数据Animal操作后的数据长度,可以看到Protobuf序列化后的长度是明显比较小,可见Protobuf的性能还是很优秀的。
在这里插入图片描述
至于Protobuf为什么能做到这些提高,一方面通过定义字段顺序完成数据映射,因此不用保存字段名,另一方面,这跟他自己定义的数据结构也有关系,对于不同的数据类型采用了不同的序列化方式,对实现原理感兴趣的可以自行了解。

本文源代码以及*.proto文件的转换工具:【下载】

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自平衡Azure

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值