google 的 protobuf 一个及其快速,以及好用的序列化框架,支持多语言之间,我们今天就使用java来进行尝试.
by the way,为什么要序列化,不序列化不行吗?这么麻烦,序列化是一种对象持久化的手段,主要是用在网络传输、RMI等场景中,为了数据的传输,所以才需要进行序列化,一般的使用中确实不用序列化.
笔者使用的是win10,jdk1.8,idea.
我们以proto3版本为例:
person_msg.proto
内容是:
syntax = "proto3";
option java_package = "com.onyx";
option java_outer_classname = "BatteryData";
message gps_data {
int64 id = 1;
string terminalId = 2;
string dataTime = 3;
double lon = 4;
double lat = 5;
float speed = 6;
int32 altitude = 7;
int32 locType = 8;
int32 gpsStatus = 9;
float direction = 10;
int32 satellite = 11;
}
注意:
* 顶部必须申明句法的版本号,如果不申明,则默认是2.0的语法。
* 下面Message节里面的字段就是业务需要的各个字段了,等号后面的数字是序号,必须指定。在3.5版本中不用指定required、等关键字了。
* gps_data 的名称格式与为生成的java文件的名称是有关系的,如果加入了下划线,则默认生成的是GpsData 这个驼峰格式的名称。当然你也可以在文件里自定义java文件的名称
如下:
option java_outer_classname = "BatteryData";
1
但是,生成的java代码中的的builder还是按照默认格式来生成的,所以,建议大家就直接按照默认规则来设计即可。
* 此外,还可以指定改java代码的包路径,命令如下:
option java_package = "com.onyx";
1
但是这里不建议使用这个功能,因为包路径会写入到生成的代码中,一旦,代码进行重构的时候,修改起来会很麻烦,还不如直接把包路径这种功能交给ide来完成
JAVA代码的生成
生成JAVA模型的命令
在命令行工具中敲入下面的命令
protoc -I=src/main/resource/proto --java_out=src/main/java src/main/resource/proto/protobuf.proto
注意中间是使用空格作为分隔符…
说明:
-I 后面是proto文件所在的目录,
–java_out 后面是生成java文件存放地址
最后一行是proto文件的名称,可以写绝对地址,也可以直接写proto文件名称
生成的.java文件很有点大,就不展示了.
你们需要的protoc.exe我放在百度网盘了,现在的CSDN上到处是要积分的,这是可恶…
https://pan.baidu.com/s/1OH0L0cwgKhWbNTLJJo3Diw这是链接...
还有 protobuf-java和protobuf-java-util两个jar包
https://pan.baidu.com/s/1gIhL6LfLQwrdHV3JJ9RUcQ
com.google.protobuf
protobuf-java
3.5.1
com.google.protobuf
protobuf-java-util
3.5.1
关于protobuf的语法不是本文的重点,因为2和3的语法还有一些差别…请自己百度.
好了,我们开始写我们的测试程序了:
我们须先要把生成的.java文件复制到项目中去:
/**
* protobuf是一种数据交换的格式,以二进制的格式进行数据交换,主要用于网络传输、配置文件、
* 数据存储等诸多领域
* 下面我们就将指定格式的信息转换成字节形式数据,然后将字节形式数据恢复成指定格式的信息
* 读者可以简单的看下.proto文件生成的BatteryData类的结构
*/
public static void main(String[] args) {
System.out.println("===== 构建一个GPS模型开始 =====");
//获得BatteryData对象
//这里的BatteryData对象构造器被私有化,我们通过通过BatteryData的内部类Builder来构建builder
BatteryData.gps_data.Builder builder = BatteryData.gps_data.newBuilder();
//BatteryData类未提供相关属性的set方法,而Student的内部类builder提供了构建Student相关属性的set方法
builder.setAltitude(1);
builder.setDataTime("2017-12-17 16:21:44");
builder.setGpsStatus(1);
builder.setLat(39.123);
builder.setLon(120.112);
builder.setDirection(30.2F);
builder.setId(100L);
BatteryData.gps_data data = builder.build();
//这里你我们将封装有数据的对象实例,转换为字节数组,用于数据传输、存储等
byte[] bytes = data.toByteArray();
System.out.println(data.toString());
System.out.println("===== 构建GPS模型结束 =====");
System.out.println("===== gps Byte 开始=====");
for(byte b : bytes){
System.out.print(b);
}
System.out.println("\n" + "bytes长度" + data.toByteString().size());
System.out.println("===== gps Byte 结束 =====");
System.out.println("===== 使用gps 反序列化生成对象开始 =====");
BatteryData.gps_data gd = null;
try {
//我们可以将该数据进行数据传输或存储,这里至于用什么技术传输就根据具体情况而定
//将字节数据转换为对应的对象实例
gd = BatteryData.gps_data.parseFrom(bytes);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.print(gd.toString());
System.out.println("===== 使用gps 反序列化生成对象结束 =====");
System.out.println("===== 使用gps 转成json对象开始 =====");
String jsonString = "";
try {
jsonString = JsonFormat.printer().print(gd);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.println(jsonString.toString());
System.out.println("json数据大小:" + jsonString.getBytes().length);
System.out.println("===== 使用gps 转成json对象结束 =====");
}
通过这个案例,你就能够明白protobuf的强大之处了.
关于protobuf3的语法,下面是几个链接可以看看.
https://www.jianshu.com/p/e9d6af587cf6
https://colobu.com/2015/01/07/Protobuf-language-guide/
https://colobu.com/2017/03/16/Protobuf3-language-guide/
好了,今天的内容就到这里了
Java Framework,欢迎各位前来交流java相关
QQ群:965125360