protobuf3的语法

本文聚焦于protobuf3编写proto接口描述文件的语法,给出了proto文件实例。还介绍了代码生成步骤,包括下载proto编译器、解压并配置path环境变量,以及使用命令生成代码,同时给出了代码使用示例和输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要讨论protobuf3在编写proto接口描述文件时的语法,下面是一个proto文件的实例:

 

syntax = "proto3";

import "address.proto";

package com.study.blog.protobuf;
option java_package = "com.study.blog.protobuf";/
option java_outer_classname="PersonProto";
option java_multiple_files = true;
option java_generic_services = true;
option optimize_for = SPEED;

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

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

3、option java_package = "com.study.blog.protobuf";//生成代码后的命令空间

4、option java_outer_classname="Person"; //这个名字不能与下文的message名字冲突,
Person已经是一个message类型,就不能作为ClassName

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

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

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

message Person{
    enum PhoneType{ //枚举类型
        option allow_alias = true; //允许设置别名,意味着等号后面的数字(标记数字)可以重复
        HOME=0;
        MOBILE=1;
        WORK=2; //实际上只是为同一个值增加了一个别名,生成代码后的格式是work = company
        COMPANY =2;
    }

    //消息类型内嵌,在消息体内部可以直接引用。如果在外层消息体中引用,格式是:Person.PhoneNumber;
    message PhoneNumber{
        PhoneType type=1;
        string phoneNumber=2;
    }

    string name =1; //string
    int32 age =2;  //Integer
    int64 ageBySeconds=3 [deprecated=true];  //long,deprecated表示属性已过时,不建议再使用,一般是文件更新时使用。
    bool isMarry=4;  //boolean
    double hight = 5; //double
    float weight =6; //float
    repeated string position = 7; //由于repeated关键字修饰,这个属性将会生成一个集合
    map<string,string> email=8; //map类型的key不能是枚举类型(enum)

    /*引用其他proto文件的message;需要在引入的message前面加上被引入
    的proto文件的package的值,即Proto文件的命名空间*/
    com.study.blog.protobuf.Address address=10;

    oneof Profession{  //在使用时,下面的三个值,只能有一个值生效
        string math=11; //以最后一次设置的值为准,如果最后一次设置的值为math,那么Profession的值就是math
        string compute=12;//如果最后一次设置的值为compute,那么Profession的值就是compute
        string chemistry=13;
    }
    PhoneNumber phoneNumber=14;
}

message PersonRequest{
   string name=1;
   int32 age=2;
   Person.PhoneNumber phonenumber=3; //引起其他消息体中的内嵌消息体
}

message PersonResponse{
    string id=1;
    Person person=2;
}

/*定义Rpc的Service,这里需要注意:下面的方法的传入参数和返回类型都必须是message,
不能是string,int32等原始类型*/
service PersonService{
    rpc getFirstPersonInfo(PersonRequest) returns (PersonResponse){}
    rpc getPersonList(PersonRequest) returns (stream PersonResponse){}
    rpc savePerson(stream PersonRequest) returns (PersonResponse){}
    rpc updatePerson(stream PersonRequest) returns (stream PersonResponse){}
}

代码生成:
 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文件

代码的使用示例:

 

 

 
  1. package com.study.blog.protobuf;

  2.  
  3. import com.google.protobuf.Any;

  4. import com.google.protobuf.ByteString;

  5.  
  6. /**

  7. * Created by zhang on 2018/2/4.

  8. */

  9. public class TestMain {

  10. public static void main(String[] args) {

  11. //创建一个address

  12. AddressInfo.Address address = AddressInfo.Address.newBuilder()

  13. .setName("home_address")

  14. .setType(AddressInfo.Address.AddressType.HOME)

  15. .setDetail("tianjing_Road_123")

  16. .build();

  17.  
  18. //创建PhoneNumber

  19. Person.PhoneNumber phoneNumber = Person.PhoneNumber.newBuilder()

  20. .setPhoneNumber("2132342134123412")

  21. .setType(Person.PhoneType.WORK)

  22. .build();

  23.  
  24. //创建一个Person

  25. Person person = Person.newBuilder()

  26. .setName("zhangsan")

  27. .setAge(23)

  28. .setAgeBySeconds(12L)

  29. .setIsMarry(false)

  30. .addPosition("teacher") //repeated,生成的代码是一个集合

  31. .addPosition("student")

  32. .addPosition("policeman")

  33. .setHight(176.23)

  34. .setWeight(Float.valueOf(12))

  35. .setAddress(address)

  36. .setPhoneNumber(phoneNumber) //内嵌类型

  37. .putEmail("QQ_email","12323123@qq.com") //map类型的赋值

  38. .putEmail("163_email","2412341234@163.com")

  39. .setMath("math") //oneof关键字修饰的属性进行赋值,设置三次,只有最后一次生效了

  40. .setChemistry("chemistry")

  41. .setCompute("compute")

  42. .build();

  43. System.out.println(person);

  44. }

  45. }

输出结果:

name: "zhangsan"
age: 23
ageBySeconds: 12
hight: 176.23
weight: 12.0
position: "teacher" //repeated修饰的属性
position: "student"
position: "policeman"
email { //map类型的属性
  key: "QQ_email"
  value: "12323123@qq.com"
}
email {  //map类型的属性
  key: "163_email"
  value: "2412341234@163.com"
}
address {
  name: "home_address"
  detail: "tianjing_Road_123"
}
compute: "compute"  //oneof修饰的属性,只有最后一次生效
phoneNumber {
  type: WORK
  phoneNumber: "2132342134123412"
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值