<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.vertx.howtos</groupId>
<artifactId>graphql-howto</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<vertx.version>5.0.0.CR2</vertx.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-stack-depchain</artifactId>
<version>${vertx.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-graphql</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<mainClass>io.vertx.howtos.graphql.GraphQLVerticle</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
实现 GraphQL 服务器
本文档将向您展示如何实现 GraphQL 服务器。
您将构建什么
您将构建一个 GraphQL 服务器来管理您的个人任务(即待办事项列表)。
该应用程序包含以下几个文件
-
tasks.graphqls
模式文件 -
Task
数据类 -
GraphQLVerticle
类
您需要什么
-
文本编辑器或 IDE
-
Java 17 或更高版本
-
Maven 或 Gradle
创建项目
此项目的代码包含功能等效的 Maven 和 Gradle 构建文件。
使用 Maven
以下是您应该使用的 pom.xml
文件的内容
pom.xml
使用 Gradle
假设您使用 Kotlin DSL 的 Gradle,您的 build.gradle.kts
文件应如下所示
build.gradle.kts
plugins {
java
application
}
repositories {
mavenCentral()
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
dependencies {
implementation(platform("io.vertx:vertx-stack-depchain:5.0.0.CR2"))
implementation("io.vertx:vertx-web-graphql")
}
application {
mainClass.set("io.vertx.howtos.graphql.GraphQLVerticle")
}
使用 Vert.x Web 和 GraphQL 管理任务
创建模式
首先,让我们为任务管理应用程序创建一个 GraphQL 模式
src/main/resources/tasks.graphqls
type Task {
id: String
description: String
completed: Boolean
}
type Query {
allTasks(uncompletedOnly: Boolean = true): [Task]
}
type Mutation {
complete(id: String!): Boolean
}
该模式定义了
-
Task
类型,包含 3 个字段:id
、description
和completed
-
allTasks
查询,返回一个任务数组,并可选地接受参数uncompletedOnly
(默认为true
) -
complete
变更,它将任务id
作为参数并返回一个 布尔值,指示操作是否成功
实现服务器
在应用程序中,任务将由 Task
类建模
src/main/java/io/vertx/howtos/graphql/Task.java
package io.vertx.howtos.graphql;
import java.util.UUID;
public record Task(String id, String description, boolean completed) {
public Task(String description) {
this(UUID.randomUUID().toString(), description, false); (1)
}
}
1 | 创建 Task 实例时会分配一个随机标识符 |
Task 类字段名称必须与相应的 GraphQL 模式类型字段名称匹配。 |
启动时,我们将创建一些条目
src/main/java/io/vertx/howtos/graphql/GraphQLVerticle.java
private Map<String, Task> initData() {
return Stream.of(
new Task("Learn GraphQL"),
new Task("Build awesome GraphQL server"),
new Task("Profit")
).collect(toMap(Task::id, identity()));
}
然后必须设置 GraphQL-Java 引擎
src/main/java/io/vertx/howtos/graphql/GraphQLVerticle.java
private GraphQL setupGraphQL() {
var schema = vertx.fileSystem().readFileBlocking("tasks.graphqls").toString(); (1)
var schemaParser = new SchemaParser();
var typeDefinitionRegistry = schemaParser.parse(schema); (2)
var runtimeWiring = newRuntimeWiring() (3)
.type("Query", builder -> builder.dataFetcher("allTasks", this::allTasks))
.type("Mutation", builder -> builder.dataFetcher("complete", this::complete))
.build();
var schemaGenerator = new SchemaGenerator();
var graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring); (4)
return GraphQL.newGraphQL(graphQLSchema).build(); (5)
}
1 | 从类路径读取模式文件 |
2 | TypeDefinitionRegistry 是 GraphQL-Java 运行时等同于模式文件定义的。 |
3 | RuntimeWiring 告诉 GraphQL-Java 如何解析类型和获取数据 |
4 | GraphQLSchema 将运行时类型定义与类型解析器和数据获取器连接起来 |
5 | 创建应用程序的 GraphQL 引擎 |
到目前为止,一切顺利。那么如何实现数据获取器呢?
src/main/java/io/vertx/howtos/graphql/GraphQLVerticle.java
private List<Task> allTasks(DataFetchingEnvironment env) {
boolean uncompletedOnly = env.getArgument("uncompletedOnly");
return tasks.values().stream()
.filter(task -> !uncompletedOnly || !task.completed())
.collect(toList());
}
allTasks
数据获取器从 DataFetchingEnvironment
获取 uncompletedOnly
参数。其值由客户端提供,或者根据模式文件中的定义设置为 true
。
不要在数据获取器中阻塞 Vert.x 事件循环。在本教程中,数据集很小且来自内存,因此以阻塞方式实现 allTasks 是安全的。当使用数据库、缓存或 Web 服务时,请确保您的数据获取器返回一个 CompletionStage 。有关更多详细信息,请参阅 Vert.x Web GraphQL 处理程序文档。 |
complete
变更的代码没有太大区别
src/main/java/io/vertx/howtos/graphql/GraphQLVerticle.java
private boolean complete(DataFetchingEnvironment env) {
String id = env.getArgument("id");
var task = tasks.get(id);
if (task == null) {
return false;
}
tasks.put(id, new Task(task.id(), task.description(), true));
return true;
}
它获取客户端提供的 id
参数,然后查找相应的任务。如果找到任务,则更新任务,并且变更返回 true
以指示成功。
快完成了!现在,让我们在 verticle 的 start
方法中将所有内容整合起来
src/main/java/io/vertx/howtos/graphql/GraphQLVerticle.java
private Map<String, Task> tasks;
@Override
public Future<?> start() {
tasks = initData();
var graphQL = setupGraphQL();
var graphQLHandler = GraphQLHandler.create(graphQL); (1)
var router = Router.router(vertx);
router.route().handler(BodyHandler.create()); (2)
router.route("/graphql").handler(graphQLHandler); (3)
return vertx.createHttpServer()
.requestHandler(router)
.listen(8080);
}
1 | 为 GraphQL-Java 对象创建 Vert.x Web GraphQL 处理程序 |
2 | 定义一个 通用 Vert.x Web 路由并设置 BodyHandler (处理 POST 请求体所必需的) |
3 | 为 GraphQL 查询定义 Vert.x Web 路由并设置 GraphQL 处理程序 |
运行应用程序
GraphQLVerticle
需要一个 main
方法
src/main/java/io/vertx/howtos/graphql/GraphQLVerticle.java
public static void main(String[] args) {
var vertx = Vertx.vertx(); (1)
vertx.deployVerticle(new GraphQLVerticle()).await(); (2)
System.out.println("Verticle deployed");
}
1 | 创建一个 Vertx 上下文 |
2 | 部署 GraphQLVerticle |
然后您可以运行应用程序
-
直接从您的 IDE 中,或
-
使用 Maven:
mvn compile exec:java
,或者 -
使用 Gradle:
./gradlew run
(Linux, macOS) 或gradlew run
(Windows)。
列出未完成的任务
要列出未完成的任务,请打开您的终端并执行此操作
http :8080/graphql query='
query {
allTasks {
id,
description
}
}'
您应该看到类似如下内容
{
"data": {
"allTasks": [
{
"description": "Learn GraphQL",
"id": "4a9f53fd-584f-4169-b725-6b320043db8b"
},
{
"description": "Profit",
"id": "03770db5-a8ad-44b3-ad6e-6fe979015088"
},
{
"description": "Build awesome GraphQL server",
"id": "6b000f72-8aa9-4f4e-9539-5da2ab11cd94"
}
]
}
}
完成任务
完成 学习 GraphQL 任务
http :8080/graphql query='
mutation {
complete(id: "4a9f53fd-584f-4169-b725-6b320043db8b")
}'
上述查询中使用的 id 必须更改为您的应用程序生成的值。 |
任务完成后,您将看到
{
"data": {
"complete": true
}
}
检索所有任务
如果您需要检索所有任务,包括已完成的任务,请务必在 allTasks
查询中将 uncompletedOnly
参数设置为 false
http :8080/graphql query='
query {
allTasks(uncompletedOnly: false) {
id
description
completed
}
}'
预期输出是
{
"data": {
"allTasks": [
{
"completed": true,
"description": "Learn GraphQL",
"id": "4a9f53fd-584f-4169-b725-6b320043db8b"
},
{
"completed": false,
"description": "Profit",
"id": "03770db5-a8ad-44b3-ad6e-6fe979015088"
},
{
"completed": false,
"description": "Build awesome GraphQL server",
"id": "6b000f72-8aa9-4f4e-9539-5da2ab11cd94"
}
]
}
}
总结
本文档涵盖了
-
Vert.x Web GraphQL 处理程序的设置,
-
实现简单的查询和变更数据获取器。