序列化协议protobuf的解释及使用

Google Protobuf是一种高效的序列化协议,通过.proto文件定义数据结构并生成类,支持Java、C++、Python等多种语言。相比Serializable、JSON、XML,Protobuf在效率和空间占用上有优势,但需要额外的编译步骤。protobuf消息定义包括message、enum等,使用时通过Builder创建对象。性能对比显示其优于传统序列化方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:

项目中看到有同事用到的protobuf,本着学习的精神来看一下这是什么?为什么使用它。先从官网了解了一下:https://developers.google.com/protocol-buffers

是什么?

Google推出的一个序列化的协议。通过定义一个.proto的数据结构化的文件,编译生成一个class,class会暴露getset等方法,方法里面通过二进制的方式进行序列化。

为什么使用它?

现在我自己经常用到的序列化也就是这几种,Serializable、自定义的序列化协议(公司的自研rpc用到)、JSON、XML。那Google的protobuf和他们比有什么优势呢?

  • Serializable

java中自带的序列化方式,会将数据序列化为二进制的数据。

优点:操作简单

缺点:《effective Java》中提到了几点:1 序列化时要显示指定版本号,否则类结构变化时会出现反序列化失败 2 反序列化创建对象时,并没有调用构造函数,可能破坏对象内部的依赖关系3 未完

  • JSON

JSON在平时中很常用,通过fastJson或者jackson来进行序列化和反序列化。使用简单。protobuf的官网没有和json做对比,过会做一下比较。

  • XML

优点:易读,跨平台

缺点:占用空间大,转换与解析性能不高,xml的dom树也比较复杂

  • 自定义序列化方式

优点:可根据业务灵活实现

缺点:实现复杂

  • protobuf

优点:效率高

缺点:需要安装protoc,略微复杂

语法:

从官网贴了一个例子来解释一下:

syntax = "proto2";

package tutorial;

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

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

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

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

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

syntax:定义这个proto文件的版本,有proto2与proto3;附proto2与proto3的语法文档,proto2:https://developers.google.com/protocol-buffers/docs/proto  proto3:https://developers.google.com/protocol-buffers/docs/proto3

package: 定义这个proto文件的坐标,类似于java的package,保证该文件的唯一。在java中,由于定义了java_package的属性,所以可以省略。但是建议保留,因为其他语言中没有java_package的属性。

java_package:定义了生成的class所在的包。在java中如果没有定义该属性的话,会使用package的值

message: 类似于java的类名,里面定义了一些属性,基础的类型有boolint32floatdouble, string,也可以定义内部的类型,枚举,例如上面的PhoneType以及PhoneNumber。 =1,=2后面作为字段的id,必须唯一。作为优化,可以将常用的字段放到id为1~15的区间(为什么呢)。每个字段必须被optional/repeated/required标记:

  • optional: 值可为空,可以通过 [detault = 值] 来设置默认值,类似于上面例子的PhoneType。对于基本类型,系统会自动设置默认值,数值类型默认值为0,string为空字符串,boolean为false
  • repeated: 数组/列表,类似于list,可以对其进行add/remove等操作。:操作时通过.add方法来修改,不要通过调用getList后再对其修改,因为getList返回的是UnmodifiableLazyStringList类型,该list不能对其修改结构(add/remove/set等操作),否则会抛异常。
        //属性名是scores,通过.addScoures来进行添加,而不是下面的model.getScoresList
        model.addScores("FDs");
        model.addScores("FDs");
        model.addScores("FDs");
        
        ProtocolStringList listsList = model.getScoresList();
        listsList.add("会抛异常");
  • required:必填,否则会抛出异常。该属性要谨慎设置。除了人为未设置导致的问题之外,可能因为程序运行异常导致未知的问题,所以尽量不使用该属性。protobuf在proto3版本中已经完全废弃该属性。

使用:

生成java类

通过protoc将.proto生成java文件,每个java文件中包含一个builder,通过此builder进行java对象的创建。需要下载protoc。可以通过brew install protobuf来下载,也可以直接从官网下载:https://github.com/protocolbuffers/protobuf/releases/tag/v3.15.7 。下载之后进行java类的生成,生成java文件有两种方式:

  • 通过命令来生成

protoc --java_out=/Users/edz/Desktop/aaaa ./WTableUserBaseInfo1.proto    --java_out表示java类的输出目录,  ./WTableUserBaseInfo1.proto表示要生成java类的.proto文件。

  • 通过idea+maven来进行生成

       1 在scr/main下面新建proto目录,将.proto文件放入该目录下;

        2 maven中加入proto的插件,其中protoSourceRoot为.proto文件的目录,protocExecutable为安装的protoc的目录

<plugin>
				<groupId>org.xolstice.maven.plugins</groupId>
				<artifactId>protobuf-maven-plugin</artifactId>
				<version>0.5.0</version>
				<configuration>
					<protoSourceRoot>/Users/edz/IdeaProjects/58/jxedt_scf_jxedtuserscf/service/src/main/proto</protoSourceRoot>
					<protocExecutable>/Users/edz/Downloads/protoc-3.15.6-osx-x86_64/bin/protoc</protocExecutable>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>compile</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

        3  通过protobuf:compile进行文件的生成

创建对象及使用:

通过newBuilder来进行对象的创建。

        AddressBookProtos.Person.Builder person = AddressBookProtos.Person.newBuilder();
        person.setEmail("FDaf");

        AddressBookProtos.Person build = person.build();
        System.out.println(build.getEmail());

性能对比:

未完待续:

附一下测试的代码:https://download.csdn.net/download/qq_38008721/16580092

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

每年进步一点点

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

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

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

打赏作者

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

抵扣说明:

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

余额充值