跳到主要内容

Jprotobuf 生成 .proto

介绍

Jprotobuf 是对 Google Protocol Buffers 的简化使用,性能同等。 使用 jprotobuf 可以无需再去了解 proto 文件操作与语法,直接使用 java 注解定义字段类型。

该模块是对 jprotobuf 的增强,如下

  1. 可以让多个对象生成在同一个 .proto 文件中。
  2. 可以不用写 jprotobuf 字段注解,进一步简化 jprotobuf 的使用。

如何安装

该模块是按需选择的功能模块,使用时需要在 pom.xml 中引入

see https://central.sonatype.com/artifact/com.iohao.net/extension-jprotobuf

pom.xml
<dependency>
<groupId>com.iohao.net</groupId>
<artifactId>extension-jprotobuf</artifactId>
<version>${ionet.version}</version>
</dependency>

如何生成 .proto

通过工具类

添加需要扫描的包名,.proto 默认生成的目录为 target/proto

void test1() {
GenerateFileKit.generate("com.iohao.example.sdk.logic.data");
}

通过 ProtoGenerateFile

  • code 3,指定 proto 生成的目录。如果不指定,默认生成的目录为 target/proto
  • code 4,添加需要扫描的包名
  • code 6,生成 .proto 文件
void test2() {
var protoGenerateFile = new ProtoGenerateFile()
.setGenerateFolder(path)
.addProtoPackage("com.iohao.example.sdk.logic.data");

protoGenerateFile.generate();
}

多模块按需生成

  • code 6,指定 proto 生成的目录。如果不指定,默认生成的目录为 target/proto
  • code 7~9,添加需要扫描的包名
  • code 10,生成 .proto 文件
void test2() {
String generateFolder = "/Users/join/gitme/game/MyGames/proto";
var protoPackageList = List.of("com.iohao.happy.robot", "com.iohao.happy.email");

var protoGenerateFile = new ProtoGenerateFile()
.setGenerateFolder(generateFolder)
.addProtoPackage(protoPackageList)
.addProtoPackage("com.iohao.happy.common.provide.proto");

protoGenerateFile.generate();
}

ProtoFileMerge 注解

在 ProtoFileMerge 注解有两个属性

  1. fileName,指定 .proto 的文件名
  2. filePackage,指定 .proto 的包名
注意

必须在类上添加此注解才能将类生成到 .proto 文件中。

使用示例

现在,我们定义 3 个类,这些类也称为协议数据类,用于请求端与服务器的通信。

数据协议类

协议数据类必须的两个注解

  • ProtobufClass,标记类是一个协议数据类。
  • ProtoFileMerge,生成 .proto 时需要的信息。
public interface TempProtoFile {
String fileName = "common.proto";
String filePackage = "pb.common";
}

/**
* MyFood
*/
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
@ProtoFileMerge(fileName = TempProtoFile.fileName, filePackage = TempProtoFile.filePackage)
public class Food {
/** id */
int id;
/** food name */
String foodName;
}

/**
* My Cat
*/
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
@ProtoFileMerge(fileName = TempProtoFile.fileName, filePackage = TempProtoFile.filePackage)
public class Cat {
/** id */
int id;
/** cat name */
String catName;
/** the food */
Food food;
/** the animalType */
AnimalTypeEnum animalType;
}

@ProtobufClass
@ProtoFileMerge(fileName = TempProtoFile.fileName, filePackage = TempProtoFile.filePackage)
public enum AnimalTypeEnum implements EnumReadable {
/** the cat */
cat(0),
/** the tiger */
tiger(10),
;

final int value;

AnimalTypeEnum(int value) {
this.value = value;
}

@Override
public int value() {
return this.value;
}
}

生成的 .proto 文件

协议数据将会生成到 common.proto 文件中,内容如下。

细心的朋友可以看见,common.proto 文件中的结构体包含了注释。 这些注释来源于我们上面定义的 java 类,这样做到了代码即注释。

syntax = "proto3";
package pb.common;

// TestAnimalTypeEnum
enum AnimalTypeEnum {
// the cat
cat = 0;
// the tiger
tiger = 10;
}

// MyCat
message Cat {
// id
int32 id = 1;
// cat name
string cat_name = 2;
// the food
Food food = 3;
// the animalType
AnimalTypeEnum animal_type = 4;
}

// MyFood
message Food {
// id
int32 id = 1;
// food name
string food_name = 2;
}

字段命名风格

生成的 .proto 字段名默认使用 UnderScoreCase 风格。

syntax = "proto3";
package common;
// 食物
message Food {
// id
sint32 id = 1;
// 食物名
string food_name = 2;
}

开发者也可以自定义生成的风格,如下设置与类属性同名

ProtoGenerateSetting.setFieldNameFunction(FieldNameGenerate::getFieldName);
syntax = "proto3";

// MyFood
message Food {
// id
int32 id = 1;
// food name
string foodName = 2;
}

注意事项

注释只支持单行,所以,请用一句话将事情描述清楚。

public class Animal {
/** id */
int id;
/** the animalType */
AnimalType animalType;
}

协议数据类必须添加的两个注解

  • ProtobufClass,标记类是一个协议数据类。
  • ProtoFileMerge,生成 .proto 时需要的信息。
@ProtobufClass
@ProtoFileMerge(fileName = TempProtoFile.fileName, filePackage = TempProtoFile.filePackage)
public class Food {
...
}

支持的类型 see https://github.com/jhunters/jprotobuf/blob/master/Document.md