Skip to main content

Vert.x Web GraphQL通过GraphQL-Java库扩展了Vert.x Web,以便您可以构建GraphQL服务器.

Tip
这是Vert.x Web GraphQL的参考文档. 强烈建议先熟悉GraphQL-Java API. 您可以先阅读GraphQL-Java文档 .
Warning
该模块具有" 技术预览"状态,这意味着API可以在版本之间进行更改.

Getting started

要使用此模块,请将以下内容添加到Maven POM文件的" 依赖项"部分:

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-web-graphql</artifactId>
 <version>3.8.4</version>
</dependency>

或者,如果您使用Gradle:

compile 'io.vertx:vertx-web-graphql:3.8.4'

Handler setup

创建一个Vert.x Web Route和一个GraphQLHandler

var GraphQLHandler = require("vertx-web-graphql-js/graph_ql_handler");
var graphQL = setupGraphQLJava();

router.route("/graphql").handler(GraphQLHandler.create(graphQL).handle);

处理程序同时处理GETPOST请求. 但是,您可以将服务限制为一种HTTP方法:

var GraphQLHandler = require("vertx-web-graphql-js/graph_ql_handler");
var graphQL = setupGraphQLJava();

router.post("/graphql").handler(GraphQLHandler.create(graphQL).handle);
Tip
GraphQLHandler不需要BodyHandler来读取POST请求内容.

GraphiQL client

在构建应用程序时,可以方便地在GraphiQL中测试GraphQL查询.

为此,请为GraphiQL资源创建一个路由,并GraphiQLHandler创建一个GraphiQLHandler

var GraphiQLHandler = require("vertx-web-graphql-js/graphi_ql_handler");
var options = {
  "enabled" : true
};

router.route("/graphiql/*").handler(GraphiQLHandler.create(options).handle);

然后浏览到http:// localhost:8080 / graphiql / .

Note
出于安全原因,默认情况下GraphiQL用户界面是禁用的. 这就是为什么必须配置GraphiQLHandlerOptions使其启用的原因.
Tip
当Vert.x Web在开发模式下运行时,将自动启用GraphiQL. 要打开开发模式,请使用VERTXWEB_ENVIRONMENT环境变量或vertxweb.environment系统属性并将其设置为dev . 在这种情况下,创建GraphiQLHandler而不更改enabled属性.

如果您的应用程序受身份验证保护,则可以动态自定义GraphiQL发送的标头:

var MultiMap = require("vertx-js/multi_map");
graphiQLHandler.graphiQLRequestHeaders(function (rc) {
  var token = rc.get("token");
  return MultiMap.caseInsensitiveMultiMap().add(Java.type("io.vertx.core.http.HttpHeaders").AUTHORIZATION, "Bearer " + token)
});

router.route("/graphiql/*").handler(graphiQLHandler.handle);

请参阅GraphiQLHandlerOptions文档以获取更多详细信息.

Enable query batching

查询批处理包括将数组而不是单个对象发布到GraphQL端点.

Vert.x Web GraphQL可以处理此类请求,但默认情况下该功能处于禁用状态. 要启用它,请创建带有选项的GraphQLHandler

var GraphQLHandler = require("vertx-web-graphql-js/graph_ql_handler");
var options = {
  "requestBatchingEnabled" : true
};

var handler = GraphQLHandler.create(graphQL, options);

Building a GraphQL server

GraphQL-Java API非常适合异步世界:异步执行策略是查询的默认设置(对于突变,是串行异步的).

为了避免阻塞事件循环 ,您要做的就是实现数据获取程序 ,这些数据获取程序返回CompletionStage而不是直接返回结果.

var dataFetcher = function (environment) {

  var completableFuture = new (Java.type("java.util.concurrent.CompletableFuture"))();

  retrieveLinksFromBackend(environment, function (ar, ar_err) {
    if (ar_err == null) {
      completableFuture.complete(ar);
    } else {
      completableFuture.completeExceptionally(ar_err);
    }
  });

  return completableFuture
};

var runtimeWiring = Java.type("graphql.schema.idl.RuntimeWiring").newRuntimeWiring().type("Query", function (builder) {
  builder.dataFetcher("allLinks", dataFetcher);
}).build();

Fetching data with callback-based APIs

实现返回CompletionStage的数据获取程序不是一项复杂的任务. 但是,当您使用基于Vert.x基于回调的API时,它需要一些样板.

This is where the VertxDataFetcher can help:

var dataFetcher = new (Java.type("io.vertx.ext.web.handler.graphql.VertxDataFetcher"))(function (environment, future) {

  retrieveLinksFromBackend(environment, future);

});

var runtimeWiring = Java.type("graphql.schema.idl.RuntimeWiring").newRuntimeWiring().type("Query", function (builder) {
  builder.dataFetcher("allLinks", dataFetcher);
}).build();

Providing data fetchers with some context

通常, GraphQLHandler将在其他路由处理程序之后声明. 例如,您可以通过身份验证保护您的应用程序.

在这种情况下,您的数据提取程序可能需要知道哪个用户已登录才能缩小结果范围. 假设您的身份验证层将一个User对象存储在RoutingContext .

您可以通过检查DataFetchingEnvironment来检索此对象:

var dataFetcher = new (Java.type("io.vertx.ext.web.handler.graphql.VertxDataFetcher"))(function (environment, future) {

  var routingContext = environment.getContext();

  var user = routingContext.get("user");

  retrieveLinksPostedBy(user, future);

});
Note
路由上下文可用于任何类型的数据获取程序,而不仅仅是VertxDataFetcher .

如果您不想将路由上下文公开给数据获取程序,请配置GraphQL处理程序以自定义上下文对象:

var GraphQLHandler = require("vertx-web-graphql-js/graph_ql_handler");
var dataFetcher = new (Java.type("io.vertx.ext.web.handler.graphql.VertxDataFetcher"))(function (environment, future) {

  // User as custom context object
  var user = environment.getContext();

  retrieveLinksPostedBy(user, future);

});

var graphQL = setupGraphQLJava(dataFetcher);

// Customize the query context object when setting up the handler
var handler = GraphQLHandler.create(graphQL).queryContext(function (routingContext) {

  return routingContext.get("user")

});

router.route("/graphql").handler(handler.handle);

JSON data results

默认的GraphQL数据获取程序为PropertyDataFetcher . 因此,它无需进一步配置即可读取域对象的字段.

但是,某些Vert.x数据客户端返回JsonArrayJsonObject结果.

如果不需要(或不想使用)域对象层,则可以将GraphQL-Java配置为使用VertxPropertyDataFetcher

var builder = Java.type("graphql.schema.idl.RuntimeWiring").newRuntimeWiring();

builder.wiringFactory(new (Java.type("graphql.schema.idl.WiringFactory"))());
Tip
VertxPropertyDataFetcher包装了PropertyDataFetcher因此您仍可以将其与域对象一起使用.

Using dataloaders

数据加载器通过批量提取请求和缓存结果来帮助您有效地加载数据.

首先,创建一个批处理加载器:

var linksBatchLoader = function (keys, environment) {

  return retrieveLinksFromBackend(keys, environment)

};
Tip
如果使用基于Vert.x回调的API,则可以使用VertxBatchLoader简化代码.

然后,配置GraphQLHandler为每个请求创建一个DataLoaderRegistry

Code not translatable

您可以使用通过WebSocket连接的Apollo WebSocketLink . 如果要向GraphQL模式添加订阅,这特别有用,但是您也可以将websocket用于查询和变异.

var ApolloWSHandler = require("vertx-web-graphql-js/apollo_ws_handler");
var graphQL = setupGraphQLJava();

router.route("/graphql").handler(ApolloWSHandler.create(graphQL).handle);
Important
为了支持graphql-ws websocket子协议,必须将其添加到服务器配置中:
var httpServerOptions = {
  "websocketSubProtocols" : "graphql-ws"
};
vertx.createHttpServer(httpServerOptions).requestHandler(router.handle).listen(8080);
Note
如果要在同一路径中支持WebSocketLink和HttpLink,则可以首先添加ApolloWSHandler,然后添加GraphQLHandler.
var ApolloWSHandler = require("vertx-web-graphql-js/apollo_ws_handler");
var GraphQLHandler = require("vertx-web-graphql-js/graph_ql_handler");
var graphQL = setupGraphQLJava();

router.route("/graphql").handler(ApolloWSHandler.create(graphQL).handle);
router.route("/graphql").handler(GraphQLHandler.create(graphQL).handle);

在这里您可以找到如何配置Apollo SubscriptionClient: https : //github.com/apollographql/subscriptions-transport-ws

Important
订阅DataFetcher必须返回org.reactivestreams.Publisher实例.

by  ICOPY.SITE