Protocol Buffers介绍
Protocal Buffers(简称protobuf)是Google开发的一种协议,用于结构化的数据序列化、反序列化,谷歌开发它的目的是提供一种比XML更好的方式来进行系统间通信。
- 与语言、平台无关,支持Java、C++、Python等多种语言
- 更简单,更小,更快,更易于维护。很适合做数据存储或RPC数据交换格式
- 扩展性、兼容性好。更新数据结构,不影响和破坏原有程序
使用ProtoBuf
一、Window安装protoc序列化工具
-
下载protoc-3.7.1-win64.zip 下载地址
-
解压安装D:\Soft\protoc-3.7.1-win64
-
配置到系统环境变量,在Path中添加D:\Soft\protoc-3.7.1-win64\bin
-
cmd中测试protoc命令
二、Idea安装protobuf插件
- 下载protobuf-jetbrains-plugin-0.13.0.zip 下载地址
- idea安装protobuf插件
三、编写Java项目测试
-
项目结构
-
创建person.proto文件
syntax = "proto3"; //指定使用proto3语法。没指定编译器默认会使用proto2
option java_package = "org.damon.rpc.protobuf.demo"; //包名
option java_outer_classname = "PersonProtobuf"; //类名
// 定义一个名为person的消息
message Person {
/*
字段规则 类型 名称 = 标识号
repeated Phone phone = 4;
字段规则:
repeated -> 字段可出现任意多次(包括0)
字段类型
int32、uint32、uint64、sint32、float、double、string等
字段名称
xx自定义
标识号
1 ~ 2^29-1, or 536,870,911(不可以使用 19000 到 19999 之间的数字,Protobuf协议实现中对这些进行了预留)
*/
enum PhoneType {
MOBILE = 0; // 枚举内部的编号第一个必须为0,并且不能重复
HOME = 1;
WORK = 2;
}
message Phone {
string number = 1;
PhoneType type = 2;
}
int32 id = 1;
string name = 2;
repeated Phone phone = 4;
}
编译成Java文件,进入person.proto文件所在目录,执行编译命令,编译好的文件会自动放在java_package指定目录下
protoc --java_out=../java person.proto
- Maven引入依赖
<!-- protobuf -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.7.1</version>
</dependency>
- 编写测试程序
package org.damon.rpc.protobuf.demo;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.util.List;
/**
* @author: wangzisong
*/
public class ProtoBufTest {
public static void main(String[] args) throws IOException {
// person构造器
PersonProtobuf.Person.Builder personBuilder = PersonProtobuf.Person.newBuilder();
//赋值
personBuilder.setId(10000);
personBuilder.setName("张麻子");
personBuilder.addPhone(PersonProtobuf.Person.Phone.newBuilder().setNumber("13412345678").setType(PersonProtobuf.Person.PhoneType.MOBILE));
personBuilder.addPhone(PersonProtobuf.Person.Phone.newBuilder().setNumber("0755-1234567").setType(PersonProtobuf.Person.PhoneType.HOME));
personBuilder.addPhone(PersonProtobuf.Person.Phone.newBuilder().setNumber("0755-6667777-032").setType(PersonProtobuf.Person.PhoneType.WORK));
System.out.println(personBuilder);
System.out.println("--------------------------");
//生成Person对象
PersonProtobuf.Person person = personBuilder.build();
// type1:byte[]
//序列化
byte[] buff = person.toByteArray();
System.out.println(buff.toString());
//反序列化 type1 byte
PersonProtobuf.Person personOut = PersonProtobuf.Person.parseFrom(buff);
System.out.println(String.format("Id:%d, 姓名:%s", personOut.getId(), personOut.getName()));
List<PersonProtobuf.Person.Phone> phoneList = personOut.getPhoneList();
for (PersonProtobuf.Person.Phone phone : phoneList) {
System.out.println(String.format("手机号:%s ,类型:%s", phone.getNumber(), phone.getType()));
}
// type2:ByteString
ByteString byteString = person.toByteString();
System.out.println(byteString.toString());
// 反序列化
personOut = PersonProtobuf.Person.parseFrom(byteString);
System.out.println(String.format("Id:%d, 姓名:%s", personOut.getId(), personOut.getName()));
}
}