Vert.x Web GraphQL通过GraphQL-Java库扩展了Vert.x Web,以便您可以构建GraphQL服务器.
Tip
|
这是Vert.x Web GraphQL的参考文档. 强烈建议先熟悉GraphQL-Java API. 您可以先阅读GraphQL-Java文档 . |
Warning
|
该模块具有" 技术预览"状态,这意味着API可以在版本之间进行更改. |
要使用此模块,请将以下内容添加到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'
创建一个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);
处理程序同时处理GET
和POST
请求. 但是,您可以将服务限制为一种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中测试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);
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
文档以获取更多详细信息.
查询批处理包括将数组而不是单个对象发布到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);
GraphQL-Java API非常适合异步世界:异步执行策略是查询的默认设置(对于突变,是串行异步的).
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();
实现返回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();
通常, 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);
默认的GraphQL数据获取程序为PropertyDataFetcher
. 因此,它无需进一步配置即可读取域对象的字段.
但是,某些Vert.x数据客户端返回JsonArray
和JsonObject
结果.
如果不需要(或不想使用)域对象层,则可以将GraphQL-Java配置为使用VertxPropertyDataFetcher
:
var builder = Java.type("graphql.schema.idl.RuntimeWiring").newRuntimeWiring();
builder.wiringFactory(new (Java.type("graphql.schema.idl.WiringFactory"))());
Tip
|
VertxPropertyDataFetcher 包装了PropertyDataFetcher 因此您仍可以将其与域对象一起使用.
|
数据加载器通过批量提取请求和缓存结果来帮助您有效地加载数据.
首先,创建一个批处理加载器:
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 实例.
|