ProtoBuf 实际应用(java)

这里field_number 就是具体的索引,wired_type的值按下表查询。

|

wired_type

|

.proto类型

|

| — | — |

|

0

|

Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum

|

|

1

|

64-bit fixed64, sfixed64, double

|

|

2

|

Length-delimited string, bytes, embedded messages, packed repeated fields

|

|

5

|

32-bit fixed32, sfixed32, float

|

对于int,bool,enum类型,value就是Varint。

而对于string,bytes,message等等类型,value是长度+原始内容编码。

  • 举例int类型存储(Varint存储原理)

存储一个int32 类型的数字,通常是4个字节。但是Varints最少只需要一个字节就可以了。

Varints规定小于128的数字都可以用一个字节来表示,比如10, 它就会用一个字节 0000 1010 来存储。

对于大于128的数字,则用更多个字节存储。

以150举例:protobuf的存储字节是 1001 0110 0000 0001。

为什么会这样标识呢?首先我们了解一个字节共8位,表示的数字是255,但是Varints只用一个字节表示小于128的数字,换句话说,就是Varints只用了8位中的7位来表示数字,而还有一位被用来干嘛了呢?

Varints在官方规定中表示,每个字节的最高位是有特殊含义,当最高位为1的时候,代表后续的字节也是该数字的一部分,后续为0的时候,则表示结束。

比如过150,二进制表示为 1001 0110。

先取后七位 001 0110, 作为第一个字节的内容。

再取余下的位,补0凑齐7位,就是000 0001。

对于intel机器,是小端字节序,低字节位于地址低的。0010110 是低字节地址,因此排在前面,因为后面的也是数字的一部分,所以高位补1,也就成了10010110。 同样的,高字节000 0001,排在后面,并且它后面没有后续字节了,所以补0,也就成了 0000 0001。

因此150 在protobuf中的表示方式为 1001 0110 0000 0001。

  • 举例string类型存储

message Test {

required string desc = 2;

}

假如把 a 设置为 “testing”的话, 那么序列化后的就是

12 07 74 65 73 74 69 64 67

其中12是key。剩下的是value。

怎么算的呢?先看12, 这里的12,是个16进制数字,其二进制位表示为 0001 0010。

0010 就是类型string的对应的Type值,根据上表,也就是2。

field_number 是 2,也就是0010,左移三位,就成了0001 0000。

按照key的计算公式,和Type值取并后就变成了 0001 0010,即12。

Value是长度加原始内容编码。

07就是长度, 代表string总长7个字节。 后面7个数字一次代表每个字母所对应的16进制表示。


下面通过java配合protobuf进行一些简单的应用,以下操作类请参考初识ProtoBuf,添加依赖或者jar包,此处我是通过maven项目进行演示。

com.google.protobuf

protobuf-java

3.6.1

java代码展示如下:

//创建对象,及属性赋值

PersonProto.Person.Builder builder = PersonProto.Person.newBuilder();

builder.setName(“Mrzhang”)

.setAge(18)

.setSex(true)

.setBirthday(System.currentTimeMillis())

.setAddress(“军事基地”)

.addCars(0, PersonProto.Car.newBuilder().setName(“兰博基尼”).setColor(“Red”).build())

.putOther(“描述”, “暂无”);

PersonProto.Person person = builder.build();

//序列化(通过protobuf生成的java类的内部方法进行序列化)

byte[] bytes = person.toByteArray();

//反序列化(通过protobuf生成的java类的内部方法进行反序列化)

try {

PersonProto.Person parseFrom = PersonProto.Person.parseFrom(bytes);

} catch (InvalidProtocolBufferException e) {

e.printStackTrace();

}

我们可以将此对象的序列化byte[]传送给其他服务,让他们通过同一个.proto文件生成相应语言的文件,通过内部的方法进行反序列化。

举例

  • 两个相互独立的项目,但是会操作同一数据,并且数据进行缓存,可以将序列化byte[]存放在Redis

  • 不同语言通过的数据通信

ProtoBuf与Json的转换

为什么要做这样的转换呢?因为我想到与数据库对应的javabean是否可以转换为proto数据这样就可以进行数据进行后续的数据交互了。(当然也有其他方式,例如反射,和复制属性等方式)

//通过fastJson进行转换

String json = JsonUtil.toJson(person);

让人意外的是,转换失败。提示信息一大堆,大致意思就是不能够转换。

通过ProtoBuf Util转换

添加依赖

com.google.protobuf

protobuf-java-util

3.6.1

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
-1715875718057)]

[外链图片转存中…(img-l71kLBtM-1715875718057)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值