Protobuf 语言指南

以一个简单例子对pb进行展开讲解

syntax = "proto3"; 

package   rpc.rpcclient.rpccall;

option  java_package="com.ppp.mpj";
option  java_multiple_files = false; 
option  java_outer_classname  = "MpjBean"; 

// 建议使用谷歌protobuf规范 遵循PB语法检查 
// 谷歌protobuf规范地址:https://developers.google.com/protocol-buffers/docs/style

// 不建议使用 google/protobuf/any.proto 
// any强依赖package type.googleapis.com/_packagename_._messagename_.   
// https://developers.google.com/protocol-buffers/docs/proto3#any 

// 在Proto中开启数据校验不仅可减少代码编写量,还能预防约75%的安全风险
import "rpc/common/validate.proto";  

service  MinOlapSql {	
	//根据班级信息,返回对应的体重sum结果信息
	rpc getStudentWeightSum(ClazzReq) returns (AuditRes);
	//根据班级信息,返回对应的体重count结果信息
	rpc getStudentWeightCount(ClazzReq) returns (AuditRes);
	//根据班级信息以及年龄阈值信息,返回对应的体重count结果信息
	rpc getStudentWeightSumWithThreshold(ClazzWithThresholdReq) returns (AuditRes);

}

enum ClassType {
    ALL = 0;
    BLADE = 1;
    PRESTO = 2;
}

message StudentReq {
	int32 sid = 1;
	string name = 2;
	double weight = 3;
	int32 age = 4;
	ClassType classid = 5;

}
message ClazzWithThresholdReq {
		ClazzReq req = 1;
		int32 agethreshold = 2;
}

message ClazzReq {    
	ClassType clazzid = 1; // 班级id   
	string clazzname = 2; // 班级名
}

message AuditRes {    
	int32 ret = 1; // 返回码    
	double res = 2; // 返回信息
	repeated StudentReq stulist = 3;
}

1、第一行的syntax指定了正在使用proto3语法,假如不指定,默认使用proto2,这必须是文件的第一个非空、非注释行。

2、Package可以避免协议消息类型键的名称冲突,之后你可以在定义消息时指定是哪个包下的字段,比如

message Foo { ... foo.bar.Open open = 1; ... }

Package在c++中对应namespace。而对于Java,包声明符会变为java的一个包(实测,在bean中全为备注),在.proto文件中可以提供一个java_package。这里就明确指定了java_package,即生成的包路径。

Protocol buffer语言中的类型名称解析类似于C++:首先在最内层查找,之后是下一层,一次类推,每个包在其父包的“内部”。“.”开头(例如,.foo.bar.Baz)意味着从最外层作用域开始查找。

Protocol buffer编译器通过导入的.proto文件来解析所有的类型名称。即使有着不同的作用域规则,各语言生成的代码也知道如何每种类型该如何使用。

3、import "address.proto"; //引入其他的proto文件,如果是其他文件夹的文件也不需要加路径,
只需要在生成代码时,选择proto文件的扫描范围时,需要将所有导入proro文件都包含在内。
通过--proto_path属性指定。

4、package com.study.blog.protobuf;     // proto文件的命名空间

5、option java_package = "com.study.blog.protobuf";    //生成代码后的命令空间,不写默认就是proto的package

6、option java_outer_classname="PersonProto";       //这个名字不能与下文的message名字冲突,Person已经是一个message类型,就不能作为ClassName。默认是proto的文件名作为className。

7、option java_multiple_files = true;      //如果为true,每个message和service都会被生成为一个类。如果是false,则所有的message和service都将会是java_outer_classname的内部类。默认为false,生成一个文件。

8、option java_generic_services = true; //是否生成Service,如果这个属性为false,
将不会生成Service的代码,即使已经在proto文件编写了service结构(proto2中的属性)

9、option optimize_for = SPEED;//对生成的代码的一种优化,有三个值:SPEED,  CODE_SIZE, LITE_RUNTIME; 表示希望生成代码是偏向执行速度,还是生成的文件大小,如果在app端,代码文件的大小是很重要的。默认为SPEED。

10、deprecated表示该字段是否被弃用。

int32 old_field = 6 [deprecated = true];

11、    int32 sid = 1;

如上所见,消息定义中每个字段都有一个唯一的编号,这些

protobuf属性C++属性java属性备注
doubledoubledouble固定8个字节
floatfloatfloat固定4个字节
int32int32int32使用变长编码,对于负数编码效率较低,如果经常使用负数,建议使用sint32
int64int64int64使用变长编码,对于负数编码效率较低,如果经常使用负数,建议使用sint64
uint32uint32int使用变长编码。(只可以表示正数)
uint64uint64long使用变长编码。(只可以表示正数)
sint32int32int采用zigzag压缩,对负数编码效率比int32高
sint64int64long采用zigzag压缩,对负数编码效率比int64高
fixed32uint32int总是4字节,如果数据>2^28,编码效率高于unit32
fixed64uint64long总是8字节,如果数据>2^56,编码效率高于unit32
sfixed32int32int总是4字节
sfixed64int64long总是8字节
boolboolboolean
stringstringString一个字符串必须是utf-8编码或者7-bit的ascii编码的文本
bytesstringByteString可能包含任意顺序的字节数据

代码生成步骤:


 1、下载proto编译器,下载链接: windows版本, linux-64
        2、下载后,将其进行解压。然后配置path环境变量,环境变量指向{加压路径}/bin

        3、使用如下命令生成代码:

protoc --proto_path=src/main/proto --proto_path=src/main/protocbuf  
       --java_out=src/main/java src/main/proto/person.proto  src/main/proto/address.proto
说明:
    --proto_path,用于指定proto文件的扫描范围,可以指定多次
    --java_out,后面接了三个路径;第一个路径是生成代码的存放路径,第二个和第三个路径是需要生成代码的proto文件

未完待续

官方文档 https://developers.google.com/protocol-buffers/docs/proto3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yann.bai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值