Protobuf是一个高性能、易扩展的序列化框架,它的性能测试有关数据可以参看官方文档。通常在TCP Socket通讯(RPC调用)相关的应用中使用;它本身非常简单,易于开发,而且结合Netty框架可以非常便捷的实现一个RPC应用程序,同时Netty也为Protobuf解决了有关Socket通讯中“半包、粘包”等问题(反序列化时,字节成帧)。
1. 安装protobuf
windows环境从https://github.com/google/protobuf/releases/tag/v3.3.0下载 protoc-3.3.0-win32.zip并解压。
2. 创建.proto文件
Protobuf需要一个schema声明文件,后缀为“.proto”的文本文件,内容样例如下:
option java_package ="cn.creditease.protobuf";
option java_outer_classname="PersonProtos";
message Person{
required string name=1;
required int32 age=2;
optional string email=3 [default="test@163.com"] ;//optional 可以为空
repeated string childs = 4 ;//[packed=true] /repeated表示这个字段的值可以允许被重复多次,对应java List<String> childs,packed=true表示压缩,但是只能压缩int32等基本类型
map<string, Account> bankaccount = 5;
}
message Account{
required string accId=1;
required string accName=2;
required double balance=3;
}
3. 生成java文件
D:\protoc-3.3.0-win32\bin>protoc --java_out=./ Person.proto
通过“–java_out”指定生成JAVA代码保存的目录,后面紧跟“.proto”文件的路径。此后我们看到生成 了Package和一个PersonProtos.java文件,我们只需要把此java文件复制到项目中即可。
4. 测试类
public class ProtobufDemo {
public static void main(String[] args) throws IOException {
PersonProtos.Person.Builder personBuilder=PersonProtos.Person.newBuilder();
personBuilder.setAge(10);
personBuilder.setName("zhagnsan");
//对应proto文件repeated string childs = 4 ;
personBuilder.addChilds("张小三");
personBuilder.addChilds("张小小三");
//map<string, Account> bankaccount = 5;
PersonProtos.Account.Builder accountBuilder= PersonProtos.Account.newBuilder();
accountBuilder.setAccId("898989898989");
accountBuilder.setAccName("张三");
accountBuilder.setBalance(2999.09);
personBuilder.putBankaccount("ICBC",accountBuilder.build());
accountBuilder.setAccId("4556689898989");
accountBuilder.setAccName("张三");
accountBuilder.setBalance(1900000);
personBuilder.putBankaccount("CMBC",accountBuilder.build());
PersonProtos.Person person=personBuilder.build();
//第一种用法
byte[] data=person.toByteArray();
System.out.println(data.length);
//第二种用法
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
//生成一个由:[字节长度][字节数据]组成的package。特别适合RPC场景
person.writeDelimitedTo(outputStream);
ByteArrayInputStream inputStream=new ByteArrayInputStream(outputStream.toByteArray());
PersonProtos.Person result=PersonProtos.Person.parseDelimitedFrom(inputStream);
System.out.println(result.toString());
}