跳到主要内容

Micronaut GraphQL

1. 简介​

Micronau t通过 micronaut-graphql 模块支持 GraphQL。

2. 发布历史​

对于这个项目,你可以在这里找到一个发布列表(含发布说明):

https://github.com/micronaut-projects/micronaut-graphql/releases

3. 快速开始​

通过命令行工具创建你的应用程序:

mn create-app helloworld --features=graphql

如果你已经有一个应用程序,添加 micronaut graphql 的依赖:

implementation("io.micronaut.graphql:micronaut-graphql:3.2.0")

通过添加到 application.yml 来配置 /graphql 端点:

graphql:
enabled: true
graphiql: # enables the /graphiql endpoint to test calls against your graph.
enabled: true

然后在 resources 文件夹中,创建一个名为 schema.graphqls 的文件。这个文件将包含你的 GraphQL 模式的定义。在我们的例子中,它将包含以下内容:

type Query {
hello(name: String): String!
}

为 hello 查询创建一个 DataFetcher:

import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import jakarta.inject.Singleton;

@Singleton
public class HelloDataFetcher implements DataFetcher<String> {

@Override
public String get(DataFetchingEnvironment env) {
String name = env.getArgument("name");
if (name == null || name.trim().length() == 0) {
name = "World";
}
return String.format("Hello %s!", name);
}
}

然后创建 GraphQL bean:

import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.core.io.ResourceResolver;
import jakarta.inject.Singleton;

import java.io.BufferedReader;
import java.io.InputStreamReader;

@Factory //
public class GraphQLFactory {

@Bean
@Singleton
public GraphQL graphQL(ResourceResolver resourceResolver, HelloDataFetcher helloDataFetcher) { //

SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();

// Parse the schema.
TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry();
typeRegistry.merge(schemaParser.parse(new BufferedReader(new InputStreamReader(
resourceResolver.getResourceAsStream("classpath:schema.graphqls").get()))));

// Create the runtime wiring.
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Query", typeWiring -> typeWiring
.dataFetcher("hello", helloDataFetcher))
.build();

// Create the executable schema.
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);

// Return the GraphQL bean.
return GraphQL.newGraphQL(graphQLSchema).build();
}
}

你应该都准备好了。通过运行 ./gradlew run 启动你的应用程序,打开你的浏览器到你的本地 graphiql,你应该能够运行以下查询:

无参查询:

query {
hello
}

返回:

{
"data": {
"hello": "Hello World!"
}
}

带参查询:

query {
hello(name: "Micronaut")
}

返回:

{
"data": {
"hello": "Hello Micronaut!"
}
}

4. 配置​

需要 Micronaut 1.0.3 或以上版本,并且你的 classpath 上必须有 micronaut-graphql 依赖:

implementation("io.micronaut.graphql:micronaut-graphql:3.2.0")

micronaut-graphql 模块包括 com.graphql-java:graphql-java 依赖关系,并提供了 Micronaut GraphQLController,使查询通过 HTTP 执行。

正如 https://graphql.org/learn/serving-over-http 所述,支持以下 HTTP 请求:

  • 带有 query、operationName 和 variables 查询参数的 GET 请求。variables 查询参数必须是 json 编码的。

  • POST 请求,带有 application/json 请求体和 key query(字符串)、operationName(字符串)和 variables(Map)。

两者都产生一个 application/json 响应。

默认情况下,GraphQL 端点暴露在 /graphql 上,但这可以通过 graphql.path 应用程序属性改变。

src/main/resources/application.yml

graphql:
enabled: true
path: /graphql
  1. 启用/禁用 GraphQL 集成。默认为 true。
  2. 配置 GraphQL 端点路径。默认为 /graphql。

你只需配置一个 graphql.GraphQL 类型的 bean,包含 GraphQL 模式和运行时布线。

4.1 配置 GraphQL Bean​

graphql.GraphQL Bean 可以通过单独使用 GraphQL Java 实现来定义,或者与其他集成库(如 GraphQL Java Tools 或 GraphQL SPQR)相结合。正如前面提到的,第一个是作为过渡依赖添加的,其他集成库必须手动添加到 classpath 中。

下面是一个典型的例子,Micronaut 工厂类使用 GraphQL Java 库配置 graphql.GraphQL Bean。

import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.core.io.ResourceResolver;
import jakarta.inject.Singleton;

import java.io.BufferedReader;
import java.io.InputStreamReader;

@Factory //
public class GraphQLFactory {

@Bean
@Singleton
public GraphQL graphQL(ResourceResolver resourceResolver, HelloDataFetcher helloDataFetcher) { //

SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();

// Parse the schema.
TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry();
typeRegistry.merge(schemaParser.parse(new BufferedReader(new InputStreamReader(
resourceResolver.getResourceAsStream("classpath:schema.graphqls").get()))));

// Create the runtime wiring.
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Query", typeWiring -> typeWiring
.dataFetcher("hello", helloDataFetcher))
.build();

// Create the executable schema.
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);

// Return the GraphQL bean.
return GraphQL.newGraphQL(graphQLSchema).build();
}
}
  1. 定义 Factory 注解以创建 Bean。
  2. 定义 GraphQL bean,它包含运行时布线和可执行模式。

在仓库中提供了各种使用不同技术的例子。

4.2 通过 websockets 配置 GraphQL​

micronaut-graphql 模块捆绑了对 GraphQL over web sockets(https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md)的支持。

必须通过 graphql.graphql-ws.enabled 应用程序属性明确启用网络套接字上的 GraphQL。虽然服务器能够通过网络套接字处理查询和突变,但并非所有客户端都支持。一些客户端有办法为订阅配置不同的端点和/或一些过滤器,以便只使用 websocket 进行订阅。

以下配置属性可以被设置:

src/main/resources/application.yml

graphql:
graphql-ws:
enabled: false
path: /graphql-ws
keep-alive-enabled: true
keep-alive-interval: 15s
  1. 启用/禁用通过网络套接字的 GraphQL。默认为 false。
  2. 配置GraphQLWs端点路径。默认为 /graphql-ws。
  3. 启用/禁用保持活力,这可能是为了防止客户重新连接而需要的。默认为 true。
  4. 配置保持活力的时间间隔,特定的客户可能需要不同的值,或者可以设置得更高以减少一些负载 15s。

有一个例子介绍了聊天,它的特点是一个非常基本的聊天应用。对于真正的应用,订阅通常是基于一些发布/订阅的解决方案。一个使用 kafka 的订阅的例子可以在这里找到,使用 micronaut 的 graphql-endpoint。

4.3 配置 GraphiQL​

micronaut-graphql 模块与 GraphiQL 捆绑在一起,这是一个用于探索 GraphQL 的浏览器 IDE。

graphiql

GraphiQL 必须通过 graphql.graphiql.enabled 应用程序属性明确启用。

可以设置以下配置属性:

src/main/resources/application.yml

graphql:
graphiql:
enabled: true
version: 0.13.2
path: /graphiql
template-path: classpath:graphiql/index.html
template-parameters:
page-title: GraphiQL
  1. 启用/禁用 GraphiQL。默认为 false。
  2. 配置 GraphiQL 版本。默认为 0.13.2。
  3. 配置 GraphiQL 的端点路径。默认为 /graphiql。
  4. 配置 GraphiQL 模板路径。默认 classpath:graphiql/index.html。
  5. 配置 GraphiQL 模板参数。默认为无。
  6. 配置 GraphiQL 页面标题。默认为 GraphiQL。

开箱即用的 GraphiQL 页面除了 GraphiQL 版本、路径和页面标题外,并没有提供很多自定义功能。它还考虑到了 graphql.path 应用程序属性,以提供与配置的 GraphQL 端点路径的无缝集成。

如果需要进一步的定制,可以提供一个自定义的 GraphiQL 模板。可以通过在 src/main/resources/graphiq/index.html 提供自定义模板,或者通过 graphiql.template-path 应用程序属性指向不同的模板位置。在这种情况下,通过 graphql.graphiql.template-parameters 应用属性动态地替换模板中的额外参数也是很有用的。

5. 仓库​

你可以在这个资源库中找到这个项目的源代码:

https://github.com/micronaut-projects/micronaut-graphql

英文链接