pb是谷歌退出的序列化数据传输格式,它以多平台支持,高压缩传输更加快速著称
1 为啥支持多平台
pb有一套自己的语法定义数据格式,根据特性的语法形式定义数据,个人可以根据需要自定义DSL进行格式转换各个平台的语言代码,当然了这样的工作量是巨大的,Google为我们提供基于多种语言的转换支持,如
2 为啥能够传输更加快速
对于模型转化的数据pb最终将数据进行了特定的byte编码,相对于xml与json来说将不必要传输的格式定义等数据给去除掉了。通信的两端则通过pb定义出的数据结构转换出的平台代码完成数据编码与解码
3 pb的缺点
pb虽然数据传输量小,但是传输数据不够直观,接收方需要反序列化才可看到数据,在开发中不利于数据的纠错
使用入门
pb是根据.proto文件定义的数据结构进行平台代码转换,一次我们需先创建以文件。在pb数据结构是以message作为一个基本的数据集合体,同时定义出针对平台兼容的数据转换类型表
代码语言:javascript复制.proto Type Notes C Type Java Type Python Type[2] Go Type Ruby Type C# Type PHP Type Dart Type
double double double float float64 Float double float double
float float float float float32 Float float float double
int32 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. int32 int int int32 Fixnum or Bignum (as required) int integer int
int64 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. int64 long int/long[3] int64 Bignum long integer/string[5] Int64
uint32 Uses variable-length encoding. uint32 int[1] int/long[3] uint32 Fixnum or Bignum (as required) uint integer int
uint64 Uses variable-length encoding. uint64 long[1] int/long[3] uint64 Bignum ulong integer/string[5] Int64
sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 Fixnum or Bignum (as required) int integer int
sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long[3] int64 Bignum long integer/string[5] Int64
fixed32 Always four bytes. More efficient than uint32 if values are often greater than 228. uint32 int[1] int/long[3] uint32 Fixnum or Bignum (as required) uint integer int
fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 256. uint64 long[1] int/long[3] uint64 Bignum ulong integer/string[5] Int64
sfixed32 Always four bytes. int32 int int int32 Fixnum or Bignum (as required) int integer int
sfixed64 Always eight bytes. int64 long int/long[3] int64 Bignum long integer/string[5] Int64
bool bool boolean bool bool TrueClass/FalseClass bool boolean bool
string A string must always contain UTF-8 encoded or 7-bit ASCII text, and cannot be longer than 232. string String str/unicode[4] string String (UTF-8) string string String
bytes May contain any arbitrary sequence of bytes no longer than 232. string ByteString str []byte String (ASCII-8BIT) ByteString string
下面我们自定义一个看看看如何
代码语言:javascript复制syntax = "proto3";
option java_package = "app.api";
message Menu{
int32 id = 1;
string name = 2;
int32 status = 3;
int32 parent = 4;
string link = 5;
}
message MainMenu{
int32 id = 1;
string name = 2;
int32 status = 3;
int32 parent = 4;
string link = 5;
repeated Menu subs = 6;
}
message MenuEntity{
repeated MainMenu menus = 1;
}
上栗中出现了几个关键点
syntax = "proto3";代表的是对应的pb版本
message 类型与struct和class
repeated代表编译出来是个数组或者list
我们看看怎么编译
代码语言:javascript复制 protoc --proto_path=./ --java_out=./ *.proto
proto_path 指定的为pb定义文件的位置
java_out 指代的是编译出的语言此处为java
*.proto 编译那个pb文件,我们此处用的通配符
使用
将编译出的Java代码拷贝项目中即可按照Java方式调用
1 序列化
代码语言:javascript复制 mutableListOf<MenuOuterClass.MainMenu.Builder>()
categories.forEach {
var mainMenu = MenuOuterClass.MainMenu.newBuilder()
mainMenu.id = it.id
mainMenu.name = it.name
mainMenu.status = it.status
mainMenu.parent = it.parent
mainMenu.link = it.link
it.subs.forEach { menu ->
var subMenu = MenuOuterClass.Menu.newBuilder()
subMenu.id = menu.id
if (!menu.name.isNullOrBlank()) {
subMenu.name = menu.name
}
subMenu.status = menu.status
subMenu.parent = menu.parent
if (!menu.link.isNullOrBlank()) {
subMenu.link = menu.link
}
mainMenu.addSubs(subMenu)
}
menus.addMenus(mainMenu)
}
Kotlin兼容Java,我们按照Kotlin代码来写
模版类似 MenuOuterClass.Menu.newBuilder()找到对应的build一个个属性赋值即即可,最后使用menus.build().toByteString()转化为byte对应的魔种结构
2数据传输
代码语言:javascript复制 response.contentType = "application/x-protobuf"
menus.build().writeTo(response.outputStream)
response.flushBuffer()
3 反序列化
通过接收到到流文件进行反序列化(此处我们的是bytestring)
代码语言:javascript复制 val decodeEntity = MenuOuterClass.MenuEntity.parseFrom(byteString)
至此,我们的就可按照对应的class进行业务操作…