gRPC 代码生成参考指南
本参考指南解释了如何配置 gRPC 代码生成。建议首先阅读官方 gRPC 指南。
启用 gRPC 代码生成
默认情况下,位于 src/main/proto
目录中的 \*.proto
文件在构建过程中会被编译成 Java 源代码。
使用 Maven
要启用 gRPC 代码生成,请将以下依赖项添加到您的项目中
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc</artifactId>
</dependency>
接下来,确保在 Quarkus Maven 插件中启用了 generate-code
阶段
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
自定义 proto 目录
默认情况下,假定 \*.proto
文件位于 src/main/proto
目录中。您可以使用 构建描述符 中的 quarkus.grpc.codegen.proto-directory
属性来配置此位置。
对于 Maven,添加以下配置
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
<configuration>
<properties>
<quarkus.grpc.codegen.proto-directory>${project.basedir}/ext/proto</quarkus.grpc.codegen.proto-directory>
</properties>
</configuration>
</execution>
</executions>
</plugin>
对于 Gradle,使用以下配置
quarkus {
quarkusBuildProperties.put("quarkus.grpc.codegen.proto-directory", "${project.projectDir}/ext/proto")
}
生成描述符集
Protocol Buffers 不包含对其自身类型的描述。因此,如果只有原始消息而没有定义其类型的相应 .proto 文件,则很难提取任何有用的数据。但是,可以使用 protocol buffers 表示 .proto 文件的内容本身。
默认情况下,Quarkus 不会生成这些描述符。Quarkus 提供了几个配置选项来生成它们。这些配置会添加到您的 application.properties
或 application.yml
文件中
-
quarkus.generate-code.grpc.descriptor-set.generate
-
设置为
true
以启用生成
-
-
quarkus.generate-code.grpc.descriptor-set.output-dir
-
将其设置为相对于项目构建目录的值(即 Maven 的
target
,Gradle 的build
) -
Maven 默认值:
target/generated-sources/grpc
-
Gradle 默认值:
$buildDir/classes/java/quarkus-generated-sources/grpc
-
-
quarkus.generate-code.grpc.descriptor-set.name
-
要生成的描述符集文件的名称
-
默认值:
descriptor_set.dsc
-
配置 gRPC 依赖项代码生成
您可能有包含要编译为 Java 源代码的 *.proto
文件的依赖项。本节介绍如何配置代码生成以在代码生成期间包含这些 \*.proto
文件。
用于导入的 Proto 文件
Protocol Buffers 规范提供了一种导入 proto
文件的方法。Quarkus 代码生成机制允许您通过在 application.properties
中设置 quarkus.generate-code.grpc.scan-for-imports
属性来控制要扫描哪些依赖项以查找可能的导入。您可以将其设置为以下值之一
-
all
- 扫描所有依赖项 -
none
- 不扫描依赖项,仅使用src/main/proto
或src/test/proto
中定义的内容 -
groupId1:artifactId1,groupId2:artifactId2
- 仅按组 ID 和构件 ID 扫描指定的依赖项。
如果未指定,则该属性默认为 com.google.protobuf:protobuf-java
。要覆盖它,请在您的 application.properties
中设置 quarkus.generate-code.grpc.scan-for-imports
属性。例如
quarkus.generate-code.grpc.scan-for-imports=all
来自依赖项的 Proto 文件
在某些情况下,您可能想使用来自其他项目的 proto
文件来生成 gRPC 存根。为此
-
在您的项目中添加对包含 proto 文件的构件的依赖项。
-
在
application.properties
中,指定您要扫描 proto 文件的依赖项。
quarkus.generate-code.grpc.scan-for-proto=<groupId>:<artifactId>
该属性的值可以是 none
(默认值),也可以是逗号分隔的 groupId:artifactId
坐标列表。
如果依赖项包含许多 proto 文件,并且您只想为其中的一部分生成类,则可以为每个依赖项指定 glob 模式。要匹配的路径是相对于依赖项中 src/main/resources
路径的路径。例如
quarkus.generate-code.grpc.scan-for-proto-include."<groupId>:<artifactId>"=foo/**,bar/**,banana/a-proto.proto
quarkus.generate-code.grpc.scan-for-proto-exclude."<groupId>:<artifactId>"=foo/private/**,bar/another-proto.proto
请注意,属性键中的 :
字符必须转义。
Kotlin 代码生成
除了生成的 Java 代码之外,protoc
还支持 生成 Kotlin 代码。
默认情况下,如果存在依赖项 io.quarkus:quarkus-kotlin
,则会启用 Kotlin 代码生成。
要显式启用/禁用此功能,请在您的 application.properties
文件中将 quarkus.generate-code.grpc.kotlin.generate
属性设置为 true
或 false
。
com.google.protobuf:protobuf-kotlin 需要作为依赖项包含在项目中。 |
跳过代码生成
您可以使用以下方法跳过 gRPC 代码生成
-
grpc.codegen.skip
系统属性:-Dgrpc.codegen.skip=true
-
您的
application.properties
文件中的quarkus.grpc.codegen.skip
属性:quarkus.grpc.codegen.skip=true
使用 protobuf-maven-plugin 从 proto 生成 Java 文件
或者,要为 proto
文件生成存根,您可以使用 protobuf-maven-plugin
。但是,建议使用 Quarkus 支持,除非您有特殊需求。
为此,请在 <properties>
部分中定义以下属性
<grpc.version>1.69.1</grpc.version>
<protoc.version>3.25.5</protoc.version>
这些属性配置 gRPC 版本和 protoc
版本。
然后,将 eu.maveniverse.maven.nisse:plugin3
和 protobuf-maven-plugin
配置添加到 build
部分
<build>
<plugins>
<plugin>
<groupId>eu.maveniverse.maven.nisse</groupId>
<artifactId>plugin3</artifactId>
<version>0.4.0</version>
<executions>
<execution>
<id>inject-properties</id>
<goals>
<goal>inject-properties</goal>
</goals>
<phase>validate</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId> (1)
<version>${protobuf-maven-plugin-version}</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact> (2)
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
<protocPlugins>
<protocPlugin>
<id>quarkus-grpc-protoc-plugin</id>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc-protoc-plugin</artifactId>
<version>{quarkus-version}</version>
<mainClass>io.quarkus.grpc.protoc.plugin.MutinyGrpcGenerator</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
<goal>test-compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- ... -->
</plugins>
</build>
1 | protobuf-maven-plugin 从您的 gRPC 服务定义(proto 文件)生成存根类。 |
2 | 类生成使用工具 protoc ,它是特定于操作系统的。这就是为什么我们使用 Nisse Maven 插件来定位与操作系统兼容的可执行文件。 |
注意:此配置指示 protobuf-maven-plugin
生成默认 gRPC 类和使用 Mutiny 的类,以适应 Quarkus 开发体验。
当使用 protobuf-maven-plugin 而不是 quarkus-maven-plugin 时,您每次更新 proto 文件时都需要重新生成类(使用 mvn compile )。 |
为了让 Nisse Maven 插件生成正确的属性,我们需要确保设置了 nisse.compat.osDetector
系统属性。这可以通过添加以下 .mvn/maven.config
文件来完成
-Dnisse.compat.osDetector=true
使用来自依赖项的生成的 gRPC 类
当 gRPC 类(是从 proto
文件生成的类)位于应用程序的依赖项中时,该依赖项需要 Jandex 索引。您可以使用 jandex-maven-plugin
创建 Jandex 索引。有关此主题的更多信息,请参阅 CDI 指南的 Bean 发现 部分。
<build>
<plugins>
<plugin>
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>3.3.2</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
如果您使用 Gradle,则可以使用以下配置
plugins {
id 'org.kordamp.gradle.jandex' version '1.1.0'
}
建议将 proto 文件打包在依赖项中,而不是生成的类,以便 Quarkus 可以生成优化的类。有关更多信息,请参阅 专用部分。 |
参数文件
当 protoc
命令行超过最大命令长度时,您可以要求 Quarkus 使用参数文件将参数传递给 protoc
命令。
要启用此功能,请在您的 application.properties
文件中将 quarkus.generate-code.grpc.use-arg-file
属性设置为 true
。
如果您在 Windows 上,并且命令行超过 8190 个字符,Quarkus 会自动使用参数文件将参数传递给 protoc
命令。
本地与下载的 protoc
为了生成 gRPC 类,Quarkus 使用来自 com.google.protobuf
组 id 的 protoc
构件。但是,为了确保对各种平台的支持,Quarkus 会自动下载 所有 可能的 protoc
构件变体。此外,Quarkus 还会下载用于生成 Java 中 gRPC 类的 protoc
和插件。例如,即使您使用 Linux,Quarkus 也会下载 Windows 和 MacOS 的 protoc
和 Java 插件构件。
下表列出了 protoc
和插件构件的不同变体
平台 | 分类符 | 依赖项 |
---|---|---|
Linux/ARM64 |
|
|
Linux/Power PC 64 位 |
|
|
Linux/S390 64 位 |
|
|
Linux/x86 32 位 |
|
|
Linux/x86 64 位 |
|
|
Mac osx/ARM64 |
|
|
Mac osx/x86 64 位 |
|
|
Windows x86 32 位 |
|
|
Windows x86 64 位 |
|
|
由于 protoc
和插件的打包(使用分类符),无法单独排除不需要的平台。
但是,您可以完全排除 protoc
依赖项,并使用 quarkus.grpc.protoc-path
系统属性来配置安装在您机器上的 protoc
可执行文件的路径。因此,您不需要下载任何 protoc
变体
protoc
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId>
</exclusion>
</exclusions>
</dependency>
quarkus.grpc.protoc-path
属性mvn clean quarkus:dev -Dquarkus.grpc.protoc-path=/path/to/protoc
使用此方法需要本地安装 protoc 。它不会下载任何 protoc 构件。 |
不幸的是,这仅适用于 protoc ,而不适用于 Java 插件。Java 插件始终会下载。 |