新网域名备案,温岭新站seo,百度搜题在线使用,高中网站建设课程proto使用说明
一、语法
指定proto语法版本
在proto文件第一行添加#xff1a;
syntax proto3目前proto有两个版本proto2和proto3,两者语法有一定的差异#xff0c;在选择的时候注意一下
定义message #xff08;1#xff09;定义: 一个message相当于java…proto使用说明
一、语法
指定proto语法版本
在proto文件第一行添加
syntax proto3目前proto有两个版本proto2和proto3,两者语法有一定的差异在选择的时候注意一下
定义message 1定义: 一个message相当于java中的实体类里面定义了不同数据类型的数据并且在结尾处标上标签序号 2嵌套一个message内部也可以定义message类型的数据 3字段格式修饰符 参数类型 参数名称字段编码值 [字段默认值] 这里是proto2的语法规则 4proto3字段格式特性不允许加修饰符(只有两个修饰符不允许加字段默认值 在proto2中修饰符有以下几种
required: 格式良好的消息必须恰好具有该字段之一。
optional一个格式良好的消息可以有零个或一个这个字段但不能超过一个。
repeated该字段可以在消息中重复任意次数包括零次。重复值的顺序将被保留。也就是表示一个数组proto2中的修饰符有
singular:默认
repeated:该字段可以在格式良好的消息中重复任意次数包括零次。重复值的顺序将被保留。例子
message Reply{// 修饰符 参数类型 参数名称标识符 [字段默认值]bool Result 1;string UUID 2;string Token 3;repeated string extra 4;//这里定义了一个Info message格式的数据Info info 5;
}message Info{string id 1;string name 2;int32 age 3;
}//定义枚举类型 第一个值必须是0
enum PhoneType {MOBILE 0;HOME 1;WORK 2;}service定义
rpc通信原理分析参考https://www.cnblogs.com/aspirant/p/8603028.html (1) 定义访问服务端的函数名称传递参数返回值 — 就是rpc通信中构建请求消息结构的 接口名称 (2) 一个service可以定义多个待调用的函数 (3) 定义方式rpc 方法名 (参数) returns (返回值) 没有返回值 就写Empty 例子
service PersonService {//添加rpc Add (Info) returns (Empty) {}//替换rpc Replace (Info) returns (Empty) {}//查询rpc Search (SearchInfo) returns (stream Info) {}//获取总数rpc Count (SearchInfo) returns (CountInfo) {}//删除rpc Delete (Id) returns (Empty) {}//导出rpc Export (Ids) returns (Id) {}
}保留标识符reserved
message中每一个字段都对应有一个标识符1,2,3,4,5,6…, 当版本更新的时候删除或者注释掉某一个字段的时候保留标识符可以让这个标识号不会被新的字段名称使用这样避免了bug等等
例如在上面的Info这个message中age这个字段的标识符是3如果在下一个版本V2中我们将age删除了不要了添加了一个叫sex的字段 1如果我们对3这个标识符做保留操作 sex这个字段标识符不能是3否则编译不通过这样是正确的合理的 2如果我们对3这个标识符不做保留操作sex这个字段标识符或者其它新的字段使用3这个标识符会导致前后V1和V2两个版本3这个标识符代表的字段不一致出现其它Bug
例子
message Persion{string id 1;string name 2;//保留3,15,9,10,11这几个标识符不能被使用reserved 3, 15, 9 to 11;//reserved location
}数据格式和Java语言格式对应表
protojava说明doubledoublefloatfloatint32int使用变长编码对于负值的效率很低如果你的域有可能有负值请使用sint64替代uint32int使用变长编码uint64long使用变长编码sint32int使用变长编码这些编码在负值时比int32高效的多sint64long使用变长编码有符号的整型值。编码时比通常的int64高效。sfixed32int总是4个字节sfixed64long总是8个字节fixed32int总是4个字节如果数值总是比总是比228大的话这个类型会比uint32高效。fixed64long总是8个字节如果数值总是比总是比256大的话这个类型会比uint64高效。boolbooleanstringString一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。bytesByteString可能包含任意顺序的字节数据。
还支持了枚举类型
数据格式默认值 (1对于strings默认是一个空string 2对于bytes默认是一个空的bytes 3对于bools默认是false 4对于数值类型默认是0 5对于枚举默认是第一个定义的枚举值必须为0; 6对于消息类型message域没有被设置确切的消息是根据语言确定的 枚举类型格式定义
例子
message SearchRequest {string query 1;int32 page_number 2;int32 result_per_page 3;enum Corpus {UNIVERSAL 0;WEB 1;IMAGES 2;LOCAL 3;NEWS 4;PRODUCTS 5;VIDEO 6;}Corpus corpus 4;
}可以将option属性中allow_alias 设置为true来为枚举类型定义相同的常量值
message MyMessage1 {enum EnumAllowingAlias {option allow_alias true;UNKNOWN 0;STARTED 1;RUNNING 1;}
}
message MyMessage2 {enum EnumNotAllowingAlias {UNKNOWN 0;STARTED 1;// RUNNING 1; // Uncommenting this line will cause a compile error inside Google and a warning message outside.}
}枚举常量值必须在32字节integer范围内。负数效率低不推荐使用
导包定义
如果想使用的消息类型定义在另一个.proto文件中可以通过导包的方式将另一个文件导入进来导包的语句如下
import myproject/other_protos.proto;场景使用test.proto中调用test2.proto文件中的DeviceInfo这个messagetest2.proto的包名是 test2package 1import “test2.proto”; 添加你需要调用哪一个proto文件 2在test.proto中调用: test2package.DeviceInfo deviceInfo 3; 例子
syntax proto3;
package testpackge;//导包
import test2.proto
message Info{string id 1;//调用Messagetest2package.DeviceInfo deviceInfo 2;
}option可选项 //是否运行生成多个java文件 option java_multiple_files false; //这个选项表明生成java类所在的包。如果在.proto文件中没有明确的声明java_package就采用默认的包名 option java_package “com.example.administrator.grpctest.proto”; //生成的java类名字 option java_outer_classname “TestProto”; //生成方式可以被设置为 SPEED, CODE_SIZE,or LITE_RUNTIME。这些值将通过如下的方式影响C及java代码的生成 option optimize_for SPEED; 1SPEED (default): protocol buffer编译器将通过在消息类型上执行序列化、语法分析及其他通用的操作。这种代码是最优的。 2CODE_SIZE: protocol buffer编译器将会产生最少量的类通过共享或基于反射的代码来实现序列化、语法分析及各种其它操作。采用该方式产生的代码将比SPEED要少得多 但是操作要相对慢些。当然实现的类及其对外的API与SPEED模式都是一样的。这种方式经常用在一些包含大量的.proto文件而且并不盲目追求速度的 应用中。 3LITE_RUNTIME: protocol buffer编译器依赖于运行时核心类库来生成代码即采用libprotobuf-lite 替代libprotobuf。这种核心类库由于忽略了一 些描述符及反射要比全类库小得多。这种模式经常在移动手机平台应用多一些。编译器采用该模式产生的方法实现与SPEED模式不相上下产生的类通过实现 MessageLite接口但它仅仅是Messager接口的一个子集 更新一个消息类型
如果一个已有的消息格式已无法满足新的需求——如要在消息中添加一个额外的字段——但是同时旧版本写的代码仍然可用。不用担心更新消息而不破坏已有代码是非常简单的。在更新时只要记住以下的规则即可。 不要更改任何已有的字段的数值标识。如果你增加新的字段使用旧格式的字段仍然可以被你新产生的代码所解析。你应该记住这些元素的默认值这样你的新代码就可以以适当的方式和旧代码产生的数据交互。相似的通过新代码产生的消息也可以被旧代码解析只不过新的字段会被忽视掉。注意未被识别的字段会在反序列化的过程中丢弃掉所以如果消息再被传递给新的代码新的字段依然是不可用的这和proto2中的行为是不同的在proto2中未定义的域依然会随着消息被序列化非required的字段可以移除——只要它们的标识号在新的消息类型中不再使用更好的做法可能是重命名那个字段例如在字段前添加“OBSOLETE_”前缀那样的话使用的.proto文件的用户将来就不会无意中重新使用了那些不该使用的标识号。int32, uint32, int64, uint64,和bool是全部兼容的这意味着可以将这些类型中的一个转换为另外一个而不会破坏向前、 向后的兼容性。如果解析出来的数字与对应的类型不相符那么结果就像在C中对它进行了强制类型转换一样例如如果把一个64位数字当作int32来 读取那么它就会被截断为32位的数字。sint32和sint64是互相兼容的但是它们与其他整数类型不兼容。string和bytes是兼容的——只要bytes是有效的UTF-8编码。嵌套消息与bytes是兼容的——只要bytes包含该消息的一个编码过的版本。fixed32与sfixed32是兼容的fixed64与sfixed64是兼容的。枚举类型与int32uint32int64和uint64相兼容注意如果值不相兼容则会被截断然而在客户端反序列化之后他们可能会有不同的处理方式例如未识别的proto3枚举类型会被保留在消息中但是他的表示方式会依照语言而定。int类型的字段总会保留他们的 Map映射
如果你希望创建一个关联映射protocol buffer提供了一种快捷的语法
mapkey_type, value_type map_field N;1其中key_type可以是任意Integer或者string类型所以除了floating和bytes的任意标量类型都是可以的value_type可以是任意类型。
例如如果你希望创建一个project的映射每个Projecct使用一个string作为key你可以像下面这样定义
mapstring, Project projects 3;Map的字段可以是repeated。序列化后的顺序和map迭代器的顺序是不确定的所以你不要期望以固定顺序处理Map当为.proto文件产生生成文本格式的时候map会按照key 的顺序排序数值化的key会按照数值排序。从序列化中解析或者融合时如果有重复的key则后一个key不会被使用当从文本格式中解析map时如果存在重复的key。 JSON映射
Proto3 支持JSON的编码规范使他更容易在不同系统之间共享数据在下表中逐个描述类型。
如果JSON编码的数据丢失或者其本身就是null这个数据会在解析成protocol buffer的时候被表示成默认值。如果一个字段在protocol buffer中表示为默认值体会在转化成JSON的时候编码的时候忽略掉以节省空间。具体实现可以提供在JSON编码中可选的默认值。
proto3JSONJSON示例注意messageobject{“fBar”: v, “g”: null, …}产生JSON对象消息字段名可以被映射成lowerCamelCase形式并且成为JSON对象键null被接受并成为对应字段的默认值enumstring“FOO_BAR”枚举值的名字在proto文件中被指定mapobject{“k”: v, …}所有的键都被转换成stringrepeated Varray[v, …]null被视为空列表booltrue, falsetrue, falsestringstring“Hello World!”bytesbase64 string“YWJjMTIzIT8kKiYoKSctPUB”int32, fixed32, uint32number1, -10, 0JSON值会是一个十进制数数值型或者string类型都会接受int64, fixed64, uint64string“1”, “-10”JSON值会是一个十进制数数值型或者string类型都会接受float, doublenumber1.1, -10.0, 0, “NaN”, “Infinity”JSON值会是一个数字或者一个指定的字符串如”NaN”,”infinity”或者”-Infinity”数值型或者字符串都是可接受的指数符号也可以接受Anyobject{“type”: “url”, “f”: v, … }如果一个Any保留一个特上述的JSON映射则它会转换成一个如下形式{type: xxx, value: yyy}否则该值会被转换成一个JSON对象type字段会被插入所指定的确定的值Timestampstring“1972-01-01T10:00:20.021Z”使用RFC 339其中生成的输出将始终是Z-归一化啊的并且使用036或者9位小数Durationstring“1.000340012s”, “1s”生成的输出总是036或者9位小数具体依赖于所需要的精度接受所有可以转换为纳秒级的精度Structobject{ … }任意的JSON对象见struct.protoWrapper typesvarious types2, “2”, “foo”, true, “true”, null, 0, …包装器在JSON中的表示方式类似于基本类型但是允许nulll并且在转换的过程中保留nullFieldMaskstring“f.fooBar,h”见fieldmask.protoListValuearray[foo, bar, …]Valuevalue任意JSON值NullValuenullJSON null
二、proto使用示例
syntax proto3;option java_multiple_files true;
option java_package com.example.administrator.grpctest.proto;
option java_outer_classname HelloWorldProto;
option optimize_for CODE_SIZE;//service package name
package proto;//服务端中的HelloWorld这个接口这个接口中可以包含多个方法
service HelloWorld {rpc sayHello (RequestP) returns (ReplyP) {}
}message ReplyP{bool Result 1;string UUID 2;string Token 3;string extra 4;
}message RequestP{string UUID 1;string Token 2;PersionInfo persionInfo 3;reserved 15, 9 to 11;
}message PersionInfo{string id 1;string name 2;int32 age 3;enmu Sex{int32 m 0;int32 w 1;}Sex sex 4;
}ring Token 3; string extra 4; }
message RequestP{ string UUID 1; string Token 2; PersionInfo persionInfo 3; reserved 15, 9 to 11; }
message PersionInfo{ string id 1; string name 2; int32 age 3; enmu Sex{ int32 m 0; int32 w 1; } Sex sex 4; }