代码生成参考
代码生成参考
包
对于在 .proto 文件中定义的每个服务,Java 代码生成会生成一个 Java 类。类名是服务的名称,后缀为 Grpc
。生成的代码的包在 .proto 文件中使用 java_package
选项指定。
例如,如果 ServiceName
在包含以下内容的 .proto 文件中定义
package grpcexample;
option java_package = "io.grpc.examples";
那么生成的类将是 io.grpc.examples.ServiceNameGrpc
。
如果未指定 java_package
,则生成的类将使用 .proto 文件中指定的 package
。应避免这种情况,因为 proto 包通常不以反向域名开头。
服务存根
生成的 Java 代码包含一个后缀为 ImplBase
的内部抽象类,例如 ServiceNameImplBase
。此类为服务定义中的每个方法定义一个 Java 方法。服务实现者可以扩展此类并实现这些方法的功能。如果未被覆盖,这些方法将向客户端返回一个错误,说明该方法未实现。
ServiceNameImplBase
中存根方法的签名取决于它处理的 RPC 的类型。gRPC 服务方法有四种类型:一元、服务器流式、客户端流式和双向流式。
一元
一元 RPC 方法 unaryExample
的服务存根签名
public void unaryExample(
RequestType request,
StreamObserver<ResponseType> responseObserver)
服务器流式
服务器流式 RPC 方法 serverStreamingExample
的服务存根签名
public void serverStreamingExample(
RequestType request,
StreamObserver<ResponseType> responseObserver)
请注意,一元和服务器流式 RPC 的签名是相同的。从客户端接收单个 RequestType
,服务实现通过调用 responseObserver.onNext(ResponseType response)
来发送其响应。
客户端流式
客户端流式 RPC 方法 clientStreamingExample
的服务存根签名
public StreamObserver<RequestType> clientStreamingExample(
StreamObserver<ResponseType> responseObserver)
双向流式
双向流式 RPC 方法 bidirectionalStreamingExample
的服务存根签名
public StreamObserver<RequestType> bidirectionalStreamingExample(
StreamObserver<ResponseType> responseObserver)
客户端和双向流式 RPC 的签名是相同的。由于客户端可以向服务发送多条消息,因此服务实现负责返回一个 StreamObserver<RequestType>
实例。每当从客户端收到其他消息时,都会调用此 StreamObserver
。
客户端存根
生成的类还包含供 gRPC 客户端使用的存根,以调用服务定义的方法。每个存根都封装了一个 Channel
,该通道由生成代码的用户提供。存根使用此通道将 RPC 发送到服务。
gRPC Java 生成三种类型的存根的代码:异步、阻塞和 future。每种类型的存根在生成的代码中都有一个对应的类,例如 ServiceNameStub
、ServiceNameBlockingStub
和 ServiceNameFutureStub
。
异步存根
通过异步存根进行的 RPC 完全通过 StreamObserver
上的回调来操作。
异步存根包含服务定义中每个方法的一个 Java 方法。
通过 ServiceNameGrpc.newStub(Channel channel)
静态方法实例化新的异步存根。
一元
一元 RPC 方法 unaryExample
的异步存根签名
public void unaryExample(
RequestType request,
StreamObserver<ResponseType> responseObserver)
服务器流式
服务器流式 RPC 方法 serverStreamingExample
的异步存根签名
public void serverStreamingExample(
RequestType request,
StreamObserver<ResponseType> responseObserver)
客户端流式
客户端流式 RPC 方法 clientStreamingExample
的异步存根签名
public StreamObserver<RequestType> clientStreamingExample(
StreamObserver<ResponseType> responseObserver)
双向流式
双向流式 RPC 方法 bidirectionalStreamingExample
的异步存根签名
public StreamObserver<RequestType> bidirectionalStreamingExample(
StreamObserver<ResponseType> responseObserver)
阻塞存根
顾名思义,通过阻塞存根进行的 RPC 会阻塞,直到服务的响应可用为止。
阻塞存根包含服务定义中每个一元和服务器流式方法的一个 Java 方法。阻塞存根不支持客户端流式或双向流式 RPC。
通过 ServiceNameGrpc.newBlockingStub(Channel channel)
静态方法实例化新的阻塞存根。
一元
一元 RPC 方法 unaryExample
的阻塞存根签名
public ResponseType unaryExample(RequestType request)
服务器流式
服务器流式 RPC 方法 serverStreamingExample
的阻塞存根签名
public Iterator<ResponseType> serverStreamingExample(RequestType request)
Future 存根
通过 future 存根进行的 RPC 将异步存根的返回值包装在 GrpcFuture<ResponseType>
中,该类实现了 com.google.common.util.concurrent.ListenableFuture
接口。
Future 存根包含服务定义中每个一元方法的一个 Java 方法。Future 存根不支持流式调用。
通过 ServiceNameGrpc.newFutureStub(Channel channel)
静态方法实例化新的 future 存根。
一元
一元 RPC 方法 unaryExample
的 future 存根签名
public ListenableFuture<ResponseType> unaryExample(RequestType request)
代码生成
通常,构建系统会处理 gRPC 生成的代码的创建。
对于基于 protobuf 的代码生成,您可以将 .proto
文件与适当的插件一起放在 src/main/proto
和 src/test/proto
目录中。
一个典型的用于生成 gRPC 和 Protocol Buffers 代码的 protobuf-maven-plugin 配置如下所示
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Eclipse 和 NetBeans 用户还应查看 os-maven-plugin
的 IDE 文档。
一个典型的 protobuf-gradle-plugin 配置如下所示
apply plugin: 'java'
apply plugin: 'com.google.protobuf'
buildscript {
repositories {
mavenCentral()
}
dependencies {
// ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier
// gradle versions
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.2.0"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.4.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
Bazel 开发人员可以使用 java_grpc_library
规则,通常如下所示
load("@grpc_java//:java_grpc_library.bzl", "java_grpc_library")
proto_library(
name = "helloworld_proto",
srcs = ["src/main/proto/helloworld.proto"],
)
java_proto_library(
name = "helloworld_java_proto",
deps = [":helloworld_proto"],
)
java_grpc_library(
name = "helloworld_java_grpc",
srcs = [":helloworld_proto"],
deps = [":helloworld_java_proto"],
)
Android 开发人员,请参阅 生成客户端代码 以供参考。
如果您希望直接调用 gRPC Java 的 protobuf 插件,命令行语法如下所示
protoc --plugin=protoc-gen-grpc-java \
--grpc-java_out="$OUTPUT_FILE" --proto_path="$DIR_OF_PROTO_FILE" "$PROTO_FILE"