生成代码参考

生成代码参考

对于 .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。每种类型的存根在生成代码中都有一个对应的类,例如 ServiceNameStubServiceNameBlockingStubServiceNameFutureStub

异步存根

通过异步存根进行的 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/protosrc/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-pluginIDE 文档

一个典型的 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"