Protobuf解决的问题:
现有的数据交换格式(XML)的解析性能差
需要编写大量的代码来解析数据
数据兼容性问题
下载protobuf Compiler
下载链接.
下载proto插件(打勾的)
创建Maven项目导入依赖
<!-- 1 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 2 -->
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 3 -->
<!-- https://mvnrepository.com/artifact/io.grpc/grpc-all -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.11.0</version>
</dependency>
<!--protobuf相关end-->
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
创建proto文件
Kari.proto中写入代码:
syntax = "proto2";//指定了用的是proto2版本语法,不写默认proto2语法
package com.kari;//定义proto的包名,可以通过package防止命名冲突。(也是生成Java类的地址)
option java_outer_classname = "Kari";//生成的Java类的名称
message Person {
optional int32 id=1;
required string name=2;
message P{
optional int32 old=1;
optional string ip=2;
repeated int32 imp=3;
}
repeated P p=3;
//枚举类
enum Sex {
MAN = 0;
WOMAN = 1;
}
optional Sex sex = 4 ;
}
proto文件生成Java类
proto生成Java类的方法有很多,这里我选择了一个看起来不是很聪明的方法
编写测试类测试:
public String Testprotobuf() {
//获取person对象
//这里的person对象构造器被私有化,我们通过person的内部类Builder来构建builder
Kari.Person.Builder kari = Kari.Person.newBuilder();
//通过person的内部类builder提供了构建Student相关属性的set方法
kari.setId(10);
kari.setName("刘四");
kari.setSex(Kari.Person.Sex.MAN);//枚举
setbidP(kari);
//序列化
Kari.Person person =kari.build();
/*
反序列化(String类型反序列化放到proto生成的Java类中)
*/
String data ="CAoSBuWImOWbmxoNCAoSA29qbxgKGAEYAiAA";
System.out.println(Base64.getEncoder().encodeToString(kari.build().toByteArray()));
byte[] decode = null;
try {
//使用base64解码读取到的字符串,
decode = Base64.getDecoder().decode(data);
} catch (Exception e) {
e.printStackTrace();
}
Kari.Person pp=null;
try {
// 将解析出来的字符串进行反序列化
pp = Kari.Person.parseFrom(decode);
} catch (Exception e) {
// 如果解析失败,就返回一个特殊的实例
pp = Kari.Person.newBuilder().setName("-1").setId(-1).build();
e.printStackTrace();
}
System.out.println(pp.toString());
System.out.println("protobuf数据大小: " + person.toByteString().size());
//再将封装有数据的对象实例,转换为字节数组,用于数据传输、存储等
byte[] stuByte = person.toByteArray();
//这里得到了字节数组后,我们可以将该数据进行数据传输或存储,这里至于用什么技术传输就根据具体情况而定
//假如这里通过传输,下面的代码接到了该数据
//接收方 ,这里为了方便我们就写在一个类里面
//将字节数据反序列化为对应的对象实例
Kari.Person person1 = null;
try {
person1 = Kari.Person.parseFrom(stuByte);
//这里得到了Student实例了,就可以根据需要来操作里面的数据了
System.out.println("实例模式:"+"\n"+person1.getP(0)+""+person1.getId()+""+person1.getName()+"_");
System.out.println((person1.getSex().getNumber()==0?"男":"女"));
System.out.println("____________________________________________-");
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
/*如何快速的进行json格式化*/
String jsonObject = "";
try {
jsonObject = JsonFormat.printer().print(person1);
} catch (InvalidProtocolBufferException e) {
e.getMessage();
}
System.out.println("Json格式:"+"\n"+jsonObject.toString());
System.out.println("json数据大小: " + jsonObject.getBytes().length);
System.out.println("____________________________________________-");
System.out.println("protobuf序列化格式:"+"\n"+kari.toString());
System.out.println("数据大小: " +kari.toString().getBytes().length);
System.out.println("_____________________________________-"+"\n");
try {
// System.out.println(kari.TextFormat.printToUnicodeString);
String decp = new String(kari.toString().getBytes(),"utf-8");
String decp = new String(kari.toString().getBytes(),"utf-8");
System.out.println(decp);//输出的中文为八进制
System.out.println(kari.getNameBytes().toStringUtf8());//输出为中文
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return kari.toString();
}
public void setbidP(Kari.Person.Builder k) {
//获取P对象
Kari.Person.P.Builder p = Kari.Person.P.newBuilder();
//获取array类型
/**
* 如果对象类型是array那不妨创建两个对象
*/
List<Integer> list = new ArrayList<Integer>();
list.add(1);list.add(2);
p.addImp(10);
p.addAllImp(list);
p.setIp("ojo").setOld(10);
k.addP(p);
}
}
执行结果示例
protobuf数据大小: 27
实例模式:
old: 10
ip: "ojo"
imp: 10
imp: 1
imp: 2
10刘四_
男
____________________________________________-
Json格式:
{
"id": 10,
"name": "刘四",
"p": [{
"old": 10,
"ip": "ojo",
"imp": [10, 1, 2]
}],
"sex": "MAN"
}
json数据大小: 120
____________________________________________-
protobuf序列化格式:
id: 10
name: "\345\210\230\345\233\233"
p {
old: 10
ip: "ojo"
imp: 10
imp: 1
imp: 2
}
sex: MAN
数据大小: 105
_____________________________________-
id: 10
name: "\345\210\230\345\233\233"
p {
old: 10
ip: "ojo"
imp: 10
imp: 1
imp: 2
}
sex: MAN
刘四
详细原文:
bui.