ProtoBuf使用说明

一、Protobuf简介

protobuf(Google Protocol Buffers)是Google提供一个具有高效的协议数据交换格式工具库(类似Json),但相比于Json,Protobuf有更高的转化效率,时间效率和空间效率都是JSON的3-5倍。参考GitHub

二、安装Protobuf环境

  • windows环境下载protoc-2.5.0-win32.zip,下载后解压将protoc.exe拷贝至C:\Windows\System32目录下即可使用。
  • linux环境下在protobuf-2.5.0.tar.gz,解压后参考README.txt安装环境。

三、protobuf语法介绍

  • message:代表了实体结构,由多个消息字段(field)组成。
  • 消息字段(field): 包括数据类型、字段名、字段规则、字段唯一标识、默认值。
  • 数据类型:常见的原子类型都支持(在FieldDescriptor::kTypeToName中有定义)
  • 字段规则:(在FieldDescriptor::kLabelToName中定义)
 required:必须初始化字段,如果没有赋值,在数据序列化时会抛出异常
 optional:可选字段,可以不必初始化。
 repeated:数据可以重复(相当于java 中的Array或List)
 字段唯一标识:序列化和反序列化将会使用到。
  • 默认值:在定义消息字段时可以给出默认值。

四、编写.proto文件

//指定protobuf语法版本
syntax = "proto2";

//包名
option java_package = "com.lhc.protobuf";
//源文件类名
option java_outer_classname = "AddressBookProtos";

// class Person
message Person {
  //required 必须设置(不能为null)
  required string name = 1;
  //int32 对应java中的int
  required int32 id = 2;
  //optional 可以为空
  optional string email = 3;

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

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }
   //repeated 重复的 (集合)
  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

五、生成java文件

windows下打开cmd窗口,执行命令protoc -I=proto文件所在目录 --java_out=java文件生成的根目录(通常src/main/java) proto文件的绝对路径
eg:protoc -I=src/main/resources/proto --java_out=src/main/java src/main/resources/proto/ProtoBufHeader.proto
生成后的文件在src/main/java目录下,可在.proto文件中定义包名。

六、使用生成的java文件

@Test
public void test() {
	//包头
	ProtoBufMsg.HsHeaderMsg.Builder headerBuilder = ProtoBufMsg.HsHeaderMsg.newBuilder();
	headerBuilder.setSrcAddr("192.168.0.1");
	headerBuilder.setDestAddr("127.0.0.1");
	headerBuilder.setAckFlag(true);
	headerBuilder.setSeqNo(3);
	headerBuilder.setTerminalType(1);
	headerBuilder.setPlatFormType(1);
	HsHeaderMsg hsHeaderMsg = headerBuilder.build();
	//消息实体
	ProtoBufMsg.BusArrLeftMsg.Builder builder = ProtoBufMsg.BusArrLeftMsg.newBuilder();
	builder.setHeader(hsHeaderMsg);
	builder.setAngle(30);
	builder.setAvgSpeed(55.5);
	builder.setLongitude(138.11111);
	builder.setLatitude(29.33333);
	builder.setMsgTime("2020-12-31 11:11:00");
	builder.setRouteID("6");
	builder.setProductID("1");
	builder.setDualSerialid("1");
	builder.setIsArrLeft("1");
	//data
	BusArrLeftMsg data = builder.build();
	//输出对象数据
	System.out.println(data.toString());
	System.out.println("===== gps Byte 开始=====");
    for(byte b : data.toByteArray()){
        System.out.print(b);
    }
    System.out.println("\n" + "bytes长度" + data.toByteString().size());
    System.out.println("===== gps Byte 结束 =====");

    System.out.println("===== 使用gps 反序列化生成对象开始 =====");
    BusArrLeftMsg gd = null;
    try {
        gd = ProtoBufMsg.BusArrLeftMsg.parseFrom(data.toByteArray());
    } catch (InvalidProtocolBufferException e) {
        e.printStackTrace();
    }
    System.out.print(gd.toString());
    System.out.println("===== 使用gps 反序列化生成对象结束 =====");
}

七、单元测试输出结果

Header {
  SrcAddr: "192.168.0.1"
  DestAddr: "127.0.0.1"
  AckFlag: true
  SeqNo: 3
  TerminalType: 1
  PlatFormType: 1
}
Longitude: 138.11111
Latitude: 29.33333
Angle: 30.0
AvgSpeed: 55.5
MsgTime: "2020-12-31 11:11:00"
RouteID: "6"
ProductID: "1"
DualSerialid: "1"
IsArrLeft: "1"

===== gps Byte 开始=====
10321011495750464954564648464918949505546484648464924132340148117708-11354-11467976425-109-5810429858561644900000062645700000-647564661950485048454950455149324949584949584848-1261154-1181149-1101149-1021149
bytes长度107
===== gps Byte 结束 =====
===== 使用gps 反序列化生成对象开始 =====
Header {
  SrcAddr: "192.168.0.1"
  DestAddr: "127.0.0.1"
  AckFlag: true
  SeqNo: 3
  TerminalType: 1
  PlatFormType: 1
}
Longitude: 138.11111
Latitude: 29.33333
Angle: 30.0
AvgSpeed: 55.5
MsgTime: "2020-12-31 11:11:00"
RouteID: "6"
ProductID: "1"
DualSerialid: "1"
IsArrLeft: "1"
===== 使用gps 反序列化生成对象结束 =====

八、总结

使用protobuf可以方便序列化和反序列化对象数据,可以有效防止序列化的过程中因为协议的不一致导致数据解析错误问题。结合消息中间件,可以方便系统间的数据传输。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值