这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天
生成客户端和服务器端代码
接下来我们需要从 .proto 的服务定义中生成 gRPC 客户端和服务器端的接口。我们通过 protocol buffer 的编译器 protoc 以及一个特殊的 gRPC Java 插件来完成。为了生成 gRPC 服务,你必须 使用proto3编译器(同时支持 proto2 和 proto3 语法)。
这个例子使用的构建系统也是 Java gRPC 本身构建的一部分——为了简单起见,我们推荐使用为这个例子 提前生成的代码。你可以参考README学习如何从你的 .proto 文件中生成代码。
从这里src/generated/main可以看到为了例子预生成的代码。
下面的类都是从我们的服务定义中生成:
-
包含了所有填充,序列化以及获取请求和应答的消息类型的
Feature.java,Point.java,Rectangle.java以及其它类文件。 -
RouteGuideGrpc.java文件包含(以及其它一些有用的代码):RouteGuide服务器要实现的一个接口RouteGuideGrpc.RouteGuide,其中所有的方法都定 义在RouteGuide服务中。- 客户端可以用来和
RouteGuide服务器交互的 存根 类。 异步的存根也实现了RouteGuide接口。
创建服务器
首先来看看我们如何创建一个 RouteGuide 服务器。如果你只对创建 gRPC 客户端感兴趣,你可以跳 过这个部分,直接到创建客户端 (当然你也可能发现它也很有意思)。
让 RouteGuide 服务工作有两个部分:
- 实现我们服务定义的生成的服务接口:做我们的服务的实际的“工作”。
- 运行一个 gRPC 服务器,监听来自客户端的请求并返回服务的响应。
你可以从[grpc-java/examples/src/main/java/io/grpc/examples/RouteGuideServer.java] (github.com/grpc/grpc-j…%E7%9C%8B%E5%88%B0%E6%88%91%E4%BB%AC%E7%9A%84) RouteGuide 服务器的实现代码。现在让我们近距离研究它是如何工作的。
实现RouteGuide
如你所见,我们的服务器有一个实现了生成的 RouteGuideGrpc.Service 接口的 RouteGuideService类:
private static class RouteGuideService implements RouteGuideGrpc.RouteGuide {
...
}
简单 RPC
routeGuideServer 实现了我们所有的服务方法。首先让我们看看最简单的类型 GetFeature,它 从客户端拿到一个 Point 对象,然后从返回包含从数据库拿到的feature信息的 Feature。
@Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
responseObserver.onNext(checkFeature(request));
responseObserver.onCompleted();
}
...
private Feature checkFeature(Point location) {
for (Feature feature : features) {
if (feature.getLocation().getLatitude() == location.getLatitude()
&& feature.getLocation().getLongitude() == location.getLongitude()) {
return feature;
}
}
// No feature was found, return an unnamed feature.
return Feature.newBuilder().setName("").setLocation(location).build();
}
getFeature() 接收两个参数:
Point: 请求StreamObserver<Feature>: 一个应答的观察者,实际上是服务器调用它应答的一个特殊接口。
要将应答返回给客户端,并完成调用:
- 如在我们的服务定义中指定的那样,我们组织并填充一个
Feature应答对象返回给客户端。在这个 例子中,我们通过一个单独的私有方法checkFeature()来实现。 - 我们使用应答观察者的
onNext()方法返回Feature。 - 我们使用应答观察者的
onCompleted()方法来指出我们已经完成了和 RPC的交互。