生成代码参考
生成代码参考
包
对于 .proto 文件中定义的每个服务,Java 代码生成会生成一个 Java 类。该类的名称是服务名称后加上 Grpc
后缀。生成代码的包通过 .proto 文件中的 java_package
选项指定。
例如,如果在包含以下内容的 .proto 文件中定义了 ServiceName
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 存根不支持流式调用。
新的 Future 存根通过静态方法 ServiceNameGrpc.newFutureStub(Channel channel)
实例化。
一元式
一元式 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"