说到做到,今天就出一个demo,其实网上protobuf和spring结合的demo有很多,可能我写的不一定就能帮助大家,但是我会把我理解的protobuf和spring结合的一些东西都写下来
首先我们需要创建一个.proto文件,如下:
就是使用创建文件的方式进行创建,后缀名是proto就可以了。
怕你们懒,就把上边文档里边的内容也贴在下边吧!
syntax = "proto2";
package proto;
option java_package = "com.example.demo.proto";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2;
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 PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
看到上边的文件内容,肯定第一感觉是懵的,这都是啥跟啥,这个为什么要这样写,那个格式为什么是那样???那就来解释一下各部分的含义:
syntax:语法,目前proto的语法有两种,一种是proto2,另外一种是proto3,这个我们后边找一个章节来详谈。
package:编译完成之后的包名(这里主要是因为我们后期会将.proto文件通过protoc命令编译成java文件来进行使用)
java_package:和package类似,也是包名,生成如果这边有设置,那么编译之后的java文件就会在这个目录下
java_outer_classname:这里是编译之后生成的java文件的名称
message:定义结构体
数据类型:
—string:默认值是空字符串,对应java的string类型
—int32:默认是0,对应是java的int类型
—int64:默认是0,对应是java的long类型
—float:默认是0.0,对应是java的float类型
—double:默认是0.0,对应是java的double类型
—bool:默认是false,对应是java的boolean类型
—bytes:对应是java的ByteString类型
字段修饰符:
—repeated:用来定义数组,一个数组可以重复出现一定次数(包括0次)
—required:值不可空
—optional:可选字段
—singular:符合语法规则的消息,包含0个或者1个这样的字段
—默认值: string code=2 [default=200];
—预留字段:reserved 6 to 8;
—可压缩字段:int32 numbers = 4 [packed=true];
其他类型:
—枚举类型:
//枚举类型,必须从0开始,序号可跨越。同一包下不能重名,所以加前缀来区别
enum Role {
Role_Admin=0;
Role_Guest=1;
Role_User=2;
Role_Other=9;
}
—Map类型:
map<key_type, value_type> map_field = N;
其中key_type可以是任意Integer或者string类型(所以,除了floating和bytes的任意标量类型都是可以的)value_type可以是任意类型。
例如,如果你希望创建一个project的映射,每个Projecct使用一个string作为key
map<string, Project> projects = 3;
好了,上边.proto文件创建的差不多了,现在我们就需要将.proto文件进行编译–>编译成java文件(这里是另外一个proto文件啊,注意一下替换文件名啥的,后边的代码也是用的这个)
syntax = "proto2";
package proto;
option java_package = "com.example.demo.proto";
option java_outer_classname = "GpsDataToFront";
message GpsData {
required string id = 1;
required string distance = 2; //路程-->required是必填-->路程本来是bigdecimal类型,这边需要考虑是否类型需要转换
optional GpsToFront gps2front = 3; //gps的坐标x,y -->是选填
repeated double speed=4 [packed=true]; //speed(速度列表) -->是选填 -->repeated在java代码中类似于list结构
}
//position位置列表
message GpsToFront{
required string id = 1;
required double x = 2;
required double y = 3;
}
#怕你手懒,把编译的命令也放到下面
protoc --java_out=./ proto文件名.proto
编译完成之后就会生成上边图片那样的一个java文件,你看他是不是在一个com.example.demo.proto目录下,这边其实是不太需要的,你们可以删除掉,就直接把.proto文件里边的那个java_package那行注释掉就可以了
下边就简单的来使用一下,proto可以用于文件流也可以用于网络流等,我的操作是文件流,后续深入的话我会补上对网络流的操作也就是类似于gRPC操作
/**
* 读取
*
* @param id 要读取数据的机器id
* @return
*/
private GpsDataToFront.GpsData dataRead(String id) {
return parsFromInputStream(id);
}
//写入到文件流中
private static void writeToOutputStream(GpsDataToFront.GpsData gpsData) {
//首先get出id
String toTxtPath = gpsData.getId();
// 这里写到一个文件流中,实际上多数会写到网络流中
File f = new File("/Users/acme/" + toTxtPath + ".txt");
FileOutputStream output;
try {
output = new FileOutputStream(f);
gpsData.writeTo(output);
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//从文件流中取出
private static GpsDataToFront.GpsData parsFromInputStream(String id) {
// 这里写到一个文件流中,实际上多数会写到网络流中
File f = new File("/Users/acme/" + id + ".txt");
FileInputStream input;
try {
GpsDataToFront.GpsData gpsData = null;
input = new FileInputStream(f);
gpsData = GpsDataToFront.GpsData.parseFrom(input);
return gpsData;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
END
今天就先写到这里,后边的话可能就是对proto语法还有他的网络流使用进行讲解,再深入的话就是对源码进行读解,时间可能会比较长,就…等着吧。如果感觉写的还可以就给点鼓励🤳