文章目录
1.介绍
序列化需要考虑?
1.序列化之后的码流大小(占用网络带宽)
2.序列化和反序列化的性能(CPU资源占用)
3.是否支持跨语言
protobuf:
1.不需要序列化与类相关的信息
2.动态伸缩性(比如int可能根本就用不到4个字节,可能2个字节就能表示数据了)
int 4字节(java) -> 1~5字节(protobuf)
1.1 Java序列化
Java对象的序列化和反序列化
Person
public class Person implements Serializable{
private static final long serialVersionUID = 2690623243047210668L;
// 基本类型不会被序列化,但会被自动封装为包装类
// 所有数据类型包装类都是可序列化的
private Integer pid;
private String pname;
private Double score;
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Person{");
sb.append("pid=").append(pid);
sb.append(", pname='").append(pname).append('\'');
sb.append(", score=").append(score);
sb.append('}');
return sb.toString();
}
}
TestSerial
public class TestSerial {
//序列化
@Test
public void SerializePerson() throws Exception{
Person person = new Person();
person.setPid(1);
person.setPname("小明");
person.setScore(98.8);
// ObjectOutputStream 对象输出流,将Person对象存储到E盘的Person.txt文件中,完成对Person对象的序列化操作
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
new File("E:/Person.txt")));
oo.writeObject(person);
System.out.println("Person对象序列化成功!");
oo.close();
}
//反序列化
@Test
public void DeserializePerson() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("E:/Person.txt")));
Person person = (Person) ois.readObject();
System.out.println("Person对象反序列化成功!");
System.out.println("person = " + person.toString());
}
@Test
public void SerializeAndDeserialize() throws IOException, ClassNotFoundException {
Person person = new Person();
person.setPid(1);
person.setPname("小明");
person.setScore(98.8);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(person);
byte[] bytes = bos.toByteArray();
System.out.println("bytes = " + Arrays.toString(bytes));
System.out.println("序列化成功!!!");
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
Person personNew = (Person)ois.readObject();
System.out.println("反序列化成功!!!");
System.out.println("personNew = " + personNew.toString());
}
}
2.使用
2.1 IDEA配置
1.安装插件,然后重启一下
2.2 添加依赖pom
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--添加protobuf依赖-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
<!--配置Maven插件-->
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.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.5.1:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.3 编写protobuf配置文件person.proto
syntax = "proto3";//指定使用语法
option java_package = "com.zy.protobuf";//指定包路径
option java_outer_classname = "PersonModel";//指定外部类名字
message Person {//内部类名字,注意和java_outer_classname区分
int32 pid = 1;
string pname = 2;
double score = 3;
}
2.4 在src\main\创建proto目录,并把配置文件存放于此
因为编译的时候,插件会默认在这个目录下查找配置文件
注意:
proto必须要设置成源代码目录
2.5 编译
编译完后,可以把proto目录给还原回去,并且把插件给注释掉,不然下次整体编译会报错,我们只需要生成的java文件即可
2.6 运行
TestProto
public class TestProto {
//序列化
private byte[] serialize(){
PersonModel.Person.Builder builder = PersonModel.Person.newBuilder();
builder.setPid(2);
builder.setPname("德玛");
builder.setScore(88.9);
PersonModel.Person person = builder.build();
return person.toByteArray();
}
//反序列化
private PersonModel.Person deserialize(byte[] data) throws Exception {
PersonModel.Person person = PersonModel.Person.parseFrom(data);
return person;
}
@Test
public void test1() throws Exception {
byte[] serialize = serialize();
System.out.println("序列化成功!!!");
System.out.println("bytes = " + Arrays.toString(serialize));
PersonModel.Person person = deserialize(serialize);
System.out.println("反序列化成功!!!");
System.out.println("person = " + person.getPid()+"*"+person.getPname()+"*"+person.getScore());
}
}
从上面可知,字节数组少了许多,这是因为protobuf把描述类的信息都加在了之前生成的PersonModel类里了,传输过程中只传必要的信息
参考
protobuf使用详解
protobuf 编码实现解析(java)
maven集成Protobuff并创建GRpc示例
添加链接描述
用Maven实现一个protobuf的Java例子
Intellij IDEA中使用Protobuf的正确姿势
protobuf 消息升级 && 动态proto
d_d