java protobuf extend_Protobuf 扩展指南

本文并非

这部分可以参考官方文档,proto3的语法在这里只做简要的介绍和整理。

一个 基础Message 的定义如下

syntax = "proto3";

import "other.proto";

message SearchRequest {

string query = 1;

int32 page_number = 2;

int32 result_per_page = 3;

}

字段一般是以 [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";" 格式定义的通过 protoc 即其插件,这个 proto 类型的文件会被生成特定语言的结构体,这种语言里面的类型和 proto 文件中的基础类型对应关系在这里,在其他类型的对应关系上,比如 enum、timestamp、duration ( timestamp, duration 为拓展类型)等,由于不同语言的实现方式不同,转换方式也有所不同,取决于 protoc 或插件的实现。protobuf (如无特别说明,下文中指 protobuf 3)的数据结构通过一个 repeated 关键字实现,同时 v3 也支持了 map 类型。protobuf 支持嵌套,不支持继承。支持 any,oneof 等特殊的结构,实际取值方式和特定语言有关。protobuf 的结构体支持转换为 json 而非二进制格式,对应关系在这里,这点值得注意,一般来说一般语言中的结构体转换 json 有自己的转换库函数,但是如果使用 protobuf 的库来转换可能转换结构有所不同,本质原因是因为 protobuf 的库转换时的标准不同。option的定义格式是 "option" optionName "=" constant ";", 比如 option java_package = "com.example.foo"; options 有内置也有自定义的。这部分和高级部分关系比较大。options并不改变整个文件声明的含义,但却能够影响特定环境下处理方式。完整的内置选项可以在 google/protobuf/descriptor.proto 找到,不同的 option 和他所在的位置对应。option 有多种类型,比如 fileOption, fieldOption, methodOption 等等当你需要自定义一些 option,方式是使用 proto2 的 extend 语法,下面给出了一个例子

import "google/protobuf/descriptor.proto";

extend google.protobuf.MessageOptions {

optional string my_option = 51234;

}

message MyMessage {

option (my_option) = "Hello world!";

}

// Java 中获取这个 option

value = my_proto_file_pb2.MyMessage.DESCRIPTOR.GetOptions()

.Extensions[my_proto_file_pb2.my_option]

另一个真实的例子,来自 google 的 http 扩展,这里插件会获取 名为 google.api.http 的 option,然后转换为 http 结构

extend google.protobuf.MethodOptions {

// See `HttpRule`.

HttpRule http = 72295728;

}

// 实际使用

service Messaging {

rpc GetMessage(GetMessageRequest) returns (Message) {

option (google.api.http) = {

get:"/v1/messages/{message_id}"

};

}

}

扩展

protobuf 描述一切

本质上,protobuf 的能力是描述 entity 和 method,基本上 entity、method 外加一些约定,就可以描述所有的协议了。事实上 google 的 api 定义 基本上都可以都可以找到 protobuf 的描述

这里 protobuf 的描述作用就可以是

一个可以被复用的类型 (或者是一种 WellKnownType)。一个 rpc 服务的输入输出类型,或者 rpc 服务的 service 以及 method。一个描述某种协议(基于 protobuf 扩展 )的元信息结构和扩展位置的约定。其他各种内置或扩展的 proto 文件元信息 key value。

甚至,protobuf 能够描述 protobuf 自己。protoc 以及插件的解析 proto 文件原理中最重要的是一个 descriptor 结构,而这个结构也是 protobuf 描述的,这是一个鸡生蛋还是蛋生鸡的关系,事实上,最初的 descriptor 是开发 compile 的开发者手动写的,经过一段时间,再用 protoc 生成 descriptor 文件,用于 protoc 文件 (似乎是一种循环依赖)。

http 扩展

如上所述,google api 中定义了如何将 grpc 映射成 http 的协议,理解这套协议以及实现,是理解扩展 protobuf 的一个很好的出发点。

首先定义 映射协议以及描述对应关系的 entity, 这个 entity比较简单,文件 大部分实在描述映射的协议,以便于实际实现方参考这个描述来实现。使用 protobuf 的 extend option 的方法来扩展协议,这之后就可以使用相关的关键字来定义 google.http.rule, 比如 option (google.api.http) = {get:"/v1/messages/{message_id}}实现插件,使用相关的 descriptor 提取 proto 中的信息,转换为 httpRule 结构体,比如 grpc-ecosystem/grpc-gateway 里面的 protoc-gen-grpc-gateway 插件就利用这种方法提取出了 httpRule 结构,然后利用这种结构来实现来 grpc 方法对应的 http handler。比如这个函数 就是提取 httpRule 结构的方法。至此就实现了 结构、协议、proto 文件、生成文件直接的对应转换。

dbdfdfa130e38c48eea98e76830269d6.pngprotobuf-http-extension

gogo 扩展

gogo-protobuf 是 protoc 的 go 语言插件的实现,在实现特定语言代码生成的基础了,实现了多种 扩展特性,原始的定义在 这里 , 有以下几类

google.protobuf.EnumOptions/EnumValueOptions:Enum 选项,如 goproto_enum_prefix 表示 enum 前缀开关google.protobuf.FileOptions:全局/文件选项,如goproto_getters_all 是全局的打开是否生成 get 函数的开关,也有对应的 MessageOptions – goproto_gettegoogle.protobuf.MessageOptions:类型选项,同上,只是作用范围不同oogle.protobuf.FieldOptions:字段选项,比较常用的有 nullable – 表示生成指针还是结构体,stdtime 表示转换 WellKnownType timestamp 为 time.Time 等

实际实现和一般的 protoc 的插件并无不同,descriptor 结构由 protoc 解析,插件从 descriptor 进一步的解析出 proto 文件结构,以及各种扩展的选项,然后生成go 语言的文件。

以 nullable 这个选项为例,生成语言文件的时候会使用 帮助函数 判断对应 field 是否设置了 Nullable 的 Extension,如果没设置或者设置为True,则生成的结构则带指针,默认值为 nil。

参考

https://colobu.com/2019/10/03/protobuf-ultimate-tutorial-in-go/https://colobu.com/2015/01/07/Protobuf-language-guide/https://blog.csdn.net/xeseo/article/details/12832577

注明:本文来自投稿,不代表服务器文档网立场,如若转载,请注明出处:https://www.fwqwd.com/5039.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值