vlambda博客
学习文章列表

日拱一卒系列(protobuf入门)

1.引子

上一次我们在聊一聊jdk序列化中,分享了在实际应用场景中如何选择编解码框架,我们说需要考虑这么几个点

  • 跨语言,因为需要在不同编程语言实现的系统之间通信传递消息

  • 编码码流要小,因为需要节省带宽,节省存储资源

  • 编解码性能要好,因为需要应对高并发、高负载

并且上一次我们说,不推荐使用jdk 的序列化,原因是jdk的序列化是java的私有协议,不能跨语言,且编码码流较大,且编解码性能慢(当时我们把jdk的序列化,与通用二进制做了对比)。

基于此,那么你可能会问了,在实际项目中,通常都会选择什么样的编解码框架呢?今天我们就来聊一聊Google提供的protobuf编解码框架,通过这篇文章,我期望分享给你

  • 什么是protobuf

  • 如何使用protobuf

2.案例

2.1.什么是protobuf

protobuf全名称是 Protocol Bufferes,它是由Google开源的序列化框架(编解码框架)。打开它的官网( https://developers.google.cn/protocol-buffers/ ),我们可以看到它有以下特点

  • 语言无关、平台无关、支持多语言(c++/c#/go/java/python)

  • 通用二进制编解码,编码码流小

  • 通用二进制编解码,编解码性能好

从官网的介绍,这不就是我们在实际应用中,选择编解码框架的最佳标准吗?更重要的一点是,protobuf使用起来非常简单,易用性好!只需要

日拱一卒系列(protobuf入门)

  • 导入protobuf依赖

  • 编写.proto文件

  • 下载protobuf 编译器,将.proto文件,编译成目标语言源代码

2.2.protobuf入门案例

2.2.1.导入依赖

<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.9.1</version></dependency><dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>3.9.1</version></dependency>

2.2.2.编写Person.proto文件

syntax = "proto2";
package com.anan.netty.protobuf;
option optimize_for = SPEED;option java_package = "com.anan.netty.protobuf";option java_outer_classname = "DataInfo";
message Person { required string name = 1; optional int32 age =2; optional string address = 3;}

2.2.3.下载protobuf编译器

2.2.4.通过编译器编译代码

protoc -I=./proto --java_out=./src ./proto/Person.proto

2.2.5.应用

public static void main(String[] args) throws Exception{ // 1.序列化 DataInfo.Person person = DataInfo.Person.newBuilder() .setName("小明") .setAge(18) .setAddress("广东省广州市天河区") .build();
byte[] personBytes = person.toByteArray(); System.out.println("【person】原生对象,姓名:" + person.getName() + ",年龄:" + person.getAge() + ",地址:" + person.getAddress()); System.out.println("【personBytes】字节数组:" + personBytes);
// 2.反序列化 System.out.println("------------------华丽丽分割线------------------"); DataInfo.Person parsePersonFrom = DataInfo.Person.parseFrom(personBytes); System.out.println("【personBytes】反序列化回对象,姓名:" + parsePersonFrom.getName() + ",年龄:" + parsePersonFrom.getAge() + ",地址:" + parsePersonFrom.getAddress());}
【person】原生对象,姓名:小明,年龄:18,地址:广东省广州市天河区【personBytes】字节数组:[B@506e1b77------------------华丽丽分割线------------------【personBytes】反序列化回对象,姓名:小明,年龄:18,地址:广东省广州市天河区
Process finished with exit code 0