如何通过GRPC调用谷歌Routing API?是否可无需GRPC使用该API?
谷歌Routing API集成:gRPC调用指南与无gRPC替代方案
1. 如何用gRPC调用谷歌Routing API?
结合你提供的官方示例代码,实现步骤如下:
前置准备
- 项目需引入必要依赖:gRPC核心库(grpc-netty、grpc-protobuf)、谷歌Maps Routing V2客户端SDK(即
com.google.maps.routing.v2.*相关类,由官方proto文件生成)。 - 拥有有效的谷歌Cloud API密钥,且已开启Routes API权限。
代码解析与运行
- API密钥注入:示例通过
RoutesInterceptor拦截gRPC请求,将API密钥放入x-goog-api-key请求头。你需要把代码里的INSERT_API_KEY_HERE替换为实际密钥,或通过环境变量传入。注意:生产环境不要用
*作为x-goog-fieldmask的值,应明确指定所需返回字段,比如routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline,减少不必要的数据传输。 - 创建gRPC通道:通过
NettyChannelBuilder连接谷歌Routing API的gRPC端点routes.googleapis.com:443(标准TLS端口)。 - 构建请求对象:比如
computeRoutes方法中,用Builder模式配置起点、终点、出行模式(DRIVE/WALK等)、路由偏好(TRAFFIC_AWARE/TRAFFIC_AWARE_OPTIMAL等)、路由修改器(是否避开高速/收费站等)等参数。 - 发起gRPC调用:使用阻塞式Stub(
RoutesBlockingStub)调用API,设置超时时间(示例中为2000毫秒),处理返回响应或异常。
你提供的完整示例代码:
package com.example; import com.google.maps.routing.v2.*; import com.google.type.LatLng; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.ClientCall; import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptors; import io.grpc.ForwardingClientCall; import io.grpc.Metadata; import io.grpc.MethodDescriptor; import io.grpc.StatusRuntimeException; import io.grpc.netty.NettyChannelBuilder; import java.util.Iterator; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; public class RoutesClient { // For more detail on inserting API keys, see: // https://cloud.google.com/endpoints/docs/grpc/restricting-api-access-with-api-keys#java // For more detail on system parameters (such as FieldMask), see: // https://cloud.google.com/apis/docs/system-parameters private static final class RoutesInterceptor implements ClientInterceptor { private final String apiKey; private static final Logger logger = Logger.getLogger(RoutesInterceptor.class.getName()); private static Metadata.Key API_KEY_HEADER = Metadata.Key.of("x-goog-api-key", Metadata.ASCII_STRING_MARSHALLER); private static Metadata.Key FIELD_MASK_HEADER = Metadata.Key.of("x-goog-fieldmask", Metadata.ASCII_STRING_MARSHALLER); public RoutesInterceptor(String apiKey) { this.apiKey = apiKey; } @Override public ClientCall interceptCall(MethodDescriptor method, CallOptions callOptions, Channel next) { logger.info("Intercepted " + method.getFullMethodName()); ClientCall call = next.newCall(method, callOptions); call = new ForwardingClientCall.SimpleForwardingClientCall(call) { @Override public void start(Listener responseListener, Metadata headers) { headers.put(API_KEY_HEADER, apiKey); // Note that setting the field mask to * is OK for testing, but discouraged in // production. // For example, for ComputeRoutes, set the field mask to // "routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline" // in order to get the route distances, durations, and encoded polylines. headers.put(FIELD_MASK_HEADER, "*"); super.start(responseListener, headers); } }; return call; } } private static final Logger logger = Logger.getLogger(RoutesClient.class.getName()); private final RoutesGrpc.RoutesBlockingStub blockingStub; public RoutesClient(Channel channel) { blockingStub = RoutesGrpc.newBlockingStub(channel); } public static Waypoint createWaypointForLatLng(double lat, double lng) { return Waypoint.newBuilder() .setLocation(Location.newBuilder().setLatLng(LatLng.newBuilder().setLatitude(lat).setLongitude(lng))) .build(); } public void computeRoutes() { ComputeRoutesRequest request = ComputeRoutesRequest.newBuilder() .setOrigin(createWaypointForLatLng(37.420761, -122.081356)) .setDestination(createWaypointForLatLng(37.420999, -122.086894)).setTravelMode(RouteTravelMode.DRIVE) .setRoutingPreference(RoutingPreference.TRAFFIC_AWARE).setComputeAlternativeRoutes(true) .setRouteModifiers( RouteModifiers.newBuilder().setAvoidTolls(false).setAvoidHighways(true).setAvoidFerries(true)) .setPolylineQuality(PolylineQuality.OVERVIEW).build(); ComputeRoutesResponse response; try { logger.info("About to send request: " + request.toString()); response = blockingStub.withDeadlineAfter(2000, TimeUnit.MILLISECONDS).computeRoutes(request); } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; } logger.info("Response: " + response.toString()); } public void computeRouteMatrix() { ComputeRouteMatrixRequest request = ComputeRouteMatrixRequest.newBuilder() .addOrigins(RouteMatrixOrigin.newBuilder().setWaypoint(createWaypointForLatLng(37.420761, -122.081356)) .setRouteModifiers(RouteModifiers.newBuilder().setAvoidTolls(false).setAvoidHighways(true) .setAvoidFerries(true))) .addOrigins(RouteMatrixOrigin.newBuilder().setWaypoint(createWaypointForLatLng(37.403184, -122.097371))) .addDestinations(RouteMatrixDestination.newBuilder() .setWaypoint(createWaypointForLatLng(37.420999, -122.086894))) .addDestinations(RouteMatrixDestination.newBuilder() .setWaypoint(createWaypointForLatLng(37.383047, -122.044651))) .setTravelMode(RouteTravelMode.DRIVE).setRoutingPreference(RoutingPreference.TRAFFIC_AWARE).build(); Iterator elements; try { logger.info("About to send request: " + request.toString()); elements = blockingStub.withDeadlineAfter(2000, TimeUnit.MILLISECONDS).computeRouteMatrix(request); } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; } while (elements.hasNext()) { logger.info("Element response: " + elements.next().toString()); } } public static void main(String[] args) throws Exception { String apiKey = System.getenv("INSERT_API_KEY_HERE"); // The standard TLS port is 443 Channel channel = NettyChannelBuilder.forAddress("routes.googleapis.com", 443).build(); channel = ClientInterceptors.intercept(channel, new RoutesInterceptor(apiKey)); RoutesClient client = new RoutesClient(channel); client.computeRoutes(); client.computeRouteMatrix(); } }
2. 无需依赖gRPC使用Routing API的方式
当然存在,谷歌Routing API提供RESTful接口,可直接通过HTTP请求调用,完全不需要gRPC相关依赖:
核心步骤
- 确定REST端点:比如
ComputeRoutes对应POST端点为https://routes.googleapis.com/directions/v2:computeRoutes,ComputeRouteMatrix对应https://routes.googleapis.com/directions/v2:computeRouteMatrix。 - 设置请求头:
x-goog-api-key:你的谷歌Cloud API密钥x-goog-fieldmask:指定所需返回字段(和gRPC要求一致,生产环境避免用*)Content-Type: application/json
- 构造JSON请求体:结构与gRPC请求对象一一对应,比如
ComputeRoutes的请求体示例:
{ "origin": { "location": { "latLng": { "latitude": 37.420761, "longitude": -122.081356 } } }, "destination": { "location": { "latLng": { "latitude": 37.420999, "longitude": -122.086894 } } }, "travelMode": "DRIVE", "routingPreference": "TRAFFIC_AWARE", "computeAlternativeRoutes": true, "routeModifiers": { "avoidTolls": false, "avoidHighways": true, "avoidFerries": true }, "polylineQuality": "OVERVIEW" }
- 发送请求:用任意HTTP客户端(比如Java的
HttpClient、OkHttp,或curl命令)发送POST请求,处理JSON格式的响应即可。
内容的提问来源于stack exchange,提问作者Chichi
相关产品推荐
相关产品推荐

