合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
## 一、概述 [ProtoBuf](https://github.com/protocolbuffers/protobuf)是一种数据格式,或者说序列化框架;与其他几种主流数据格式比较,它有如下特点: * **JSON**:一般在web项目中广泛使用,主要是由于浏览器的支持非常好,内部构建了与多函数来支持JSON。具有可读性; * **XML**:在WebService中广泛使用,但是过于冗余(毕竟是通过标签进行标识)。也具有可读性; * **ProtoBuf**:适合高性能,对响应速度有要求的数据传输场景。由于是二进制数据格式需要编码和解码。不具有可读性。在官网上描述ProtoBuf比XML小3到10倍,快20到100倍; ## 二、快速入门 ### **核心原理** 核心上,通讯的产生者通过**proto文件**生成二进制传送到接受端,接收端依据proto文件,解析出原始内容; ### **结构定义** ~~~protobuf message xxx { 字段规则 类型 名称 = 字段编号; } ~~~ >[info] 规则: > // 字段规则:required -> 字段只能也必须出现 1 次 > // 字段规则:optional -> 字段可出现 0 次或1次 > // 字段规则:repeated -> 字段可出现任意多次(包括 0) > // 数据类型:int32、int64、sint32、sint64、string、32-bit .... > // 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字) > | .proto Type | 说明 | C++ Type | Java Type | Python Type\[2\] | Go Type | | --- | :-- | :-- | :-- | :-- | :-- | | double |   | double | double | float | float64 | | float |   | float | float | float | float32 | | int32 | 使用可变长度编码。对负数进行编码时比较低效 – 如果你的字段要使用负数值,请使用sint32来代替。 | int32 | int | int | int | | int64 | 使用可变长度编码。对负数进行编码时比较低效 – 如果你的字段要使用负数值,请使用sint64来代替。 | int64 | long | int/long\[3\] | int64 | | uint32 | 使用可变长度编码 | uint32 | int\[1\] | int/long\[3\] | uint32 | | uint64 | 使用可变长度编码 | uint64 | long\[1\] | int/long\[3\] | uint64 | ### **基于protoc.exe把proto文件转为java数据结构文件** 举例: 一个简单的proto文件: ``` syntax = "proto3"; package org.ray.framework.sample; import "google/protobuf/timestamp.proto"; option java_multiple_files = true; option java_package = "org.ray.framework.sample"; option java_outer_classname = "AddressBookProto"; // [START messages] message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; } // [END messages] ``` ``` protoc --java_out=./javasrc ./AddressBook.proto ``` ![](https://img.kancloud.cn/6b/e3/6be3895e25cc3c7c567eb7b2da15e25e_677x457.png) 可以看到,javasrc目录下,生成了对应的文件; ![](https://img.kancloud.cn/0c/e1/0ce1d2c3a36ef5ae8a543f39b785d587_804x287.png) ### **使用java文件** 将生成的java文件,纳入java工程,基于protobuf-java; ![](https://img.kancloud.cn/7c/0f/7c0fa7a932e41af19a334e459d6b2347_1366x736.png) 需先确保导入了protobuf-java类库; ``` <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>3.17.3</version> </dependency> ``` 简单的使用,将java对象转为protoc报文: ``` public static void main(String... args) { org.ray.framework.sample.Person.Builder builder = Person.newBuilder().setEmail("a").setId(1).setName("ok"); byte[] messageBody = builder.build().toByteArray(); System.out.println("java对象转protoprof:"+new String(messageBody)); // Person person = Person.parseFrom(messageBody); System.out.println("protoprof转java对象:"+person.toString()); } ``` 效果: ![](https://img.kancloud.cn/5b/57/5b572c8bc5285949b5d7a8daae3715ab_1366x736.png)