Spring for GraphQL

如果你想构建 GraphQL 应用程序,你可以利用 Spring Boot 为 Spring for GraphQL 提供的自动配置。 Spring for GraphQL 项目基于 GraphQL Java。 你至少需要 spring-boot-starter-graphql starter。 由于 GraphQL 是传输无关的,你还需要在应用程序中添加一个或多个额外的 starter 来通过 Web 暴露你的 GraphQL API:

Starter Transport Implementation

spring-boot-starter-web

HTTP

Spring MVC

spring-boot-starter-websocket

WebSocket

WebSocket for Servlet apps

spring-boot-starter-webflux

HTTP, WebSocket

Spring WebFlux

spring-boot-starter-rsocket

TCP, WebSocket

Spring WebFlux on Reactor Netty

GraphQL Schema

Spring GraphQL 应用程序在启动时需要定义 schema。 默认情况下,你可以在 src/main/resources/graphql/** 下编写 ".graphqls" 或 ".gqls" schema 文件,Spring Boot 会自动获取它们。 你可以使用 spring.graphql.schema.locations 自定义位置,使用 spring.graphql.schema.file-extensions 自定义文件扩展名。

注意:如果你希望 Spring Boot 在该位置检测所有应用程序模块和依赖项中的 schema 文件, 你可以将 spring.graphql.schema.locations 设置为 "classpath*:graphql/**/"(注意 classpath*: 前缀)。

在以下章节中,我们将考虑这个示例 GraphQL schema,它定义了两个类型和两个查询:

type Query {
    greeting(name: String! = "Spring"): String!
    project(slug: ID!): Project
}

""" A Project in the Spring portfolio """
type Project {
    """ Unique string id used in URLs """
    slug: ID!
    """ Project name """
    name: String!
    """ URL of the git repository """
    repositoryUrl: String!
    """ Current support status """
    status: ProjectStatus!
}

enum ProjectStatus {
    """ Actively supported by the Spring team """
    ACTIVE
    """ Supported by the community """
    COMMUNITY
    """ Prototype, not officially supported yet  """
    INCUBATING
    """ Project being retired, in maintenance mode """
    ATTIC
    """ End-Of-Lifed """
    EOL
}

注意:默认情况下,https://spec.graphql.org/draft/#sec-Introspection[字段内省] 将在 schema 上被允许,因为它是 GraphiQL 等工具所必需的。 如果你不希望暴露有关 schema 的信息,可以通过将 spring.graphql.schema.introspection.enabled 设置为 false 来禁用内省。

GraphQL RuntimeWiring

GraphQL Java RuntimeWiring.Builder 可用于注册自定义标量类型、指令、类型解析器、DataFetcher 等。 你可以在 Spring 配置中声明 RuntimeWiringConfigurer bean 来获取对 RuntimeWiring.Builder 的访问权限。 Spring Boot 检测这些 bean 并将它们添加到 GraphQlSource builder

然而,通常应用程序不会直接实现 DataFetcher,而是创建 注解控制器。 Spring Boot 将自动检测带有注解处理方法的 @Controller 类,并将它们注册为 DataFetcher。 以下是我们问候查询的示例实现,使用 @Controller 类:

  • Java

  • Kotlin

import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;

@Controller
public class GreetingController {

	@QueryMapping
	public String greeting(@Argument String name) {
		return "Hello, " + name + "!";
	}

}
import org.springframework.graphql.data.method.annotation.Argument
import org.springframework.graphql.data.method.annotation.QueryMapping
import org.springframework.stereotype.Controller

@Controller
class GreetingController {

	@QueryMapping
	fun greeting(@Argument name: String): String {
		return "Hello, $name!"
	}

}

Querydsl 和 QueryByExample Repositories 支持

Spring Data 提供对 Querydsl 和 QueryByExample repositories 的支持。 Spring GraphQL 可以 将 Querydsl 和 QueryByExample repositories 配置为 DataFetcher

使用 @GraphQlRepository 注解并扩展以下之一的 Spring Data repositories:

将被 Spring Boot 检测并被视为匹配顶级查询的 DataFetcher 的候选者。

传输

HTTP 和 WebSocket

GraphQL HTTP 端点默认为 HTTP POST /graphql。 它还支持仅用于订阅的 Server Sent Events 的 "text/event-stream" 媒体类型。 可以使用 spring.graphql.path 自定义路径。

提示:Spring MVC 和 Spring WebFlux 的 HTTP 端点由 RouterFunction bean 提供,其 @Order0。 如果你定义自己的 RouterFunction bean,你可能需要添加适当的 @Order 注解以确保它们正确排序。

GraphQL WebSocket 端点默认关闭。要启用它:

  • 对于 Servlet 应用程序,添加 WebSocket starter spring-boot-starter-websocket

  • 对于 WebFlux 应用程序,不需要额外的依赖

  • 对于两者,必须设置 spring.graphql.websocket.path 应用程序属性

Spring GraphQL 提供了 Web 拦截 模型。 这对于从 HTTP 请求头中检索信息并将其设置在 GraphQL 上下文中,或从同一上下文中获取信息并将其写入响应头非常有用。 使用 Spring Boot,你可以声明一个 WebGraphQlInterceptor bean 以将其注册到 Web 传输。

Spring MVCSpring WebFlux 支持 CORS(跨源资源共享)请求。 CORS 是 Web 配置的关键部分,适用于从使用不同域的浏览器访问的 GraphQL 应用程序。

Spring Boot 支持 spring.graphql.cors.* 命名空间下的许多配置属性;以下是一个简短的配置示例:

  • Properties

  • YAML

spring.graphql.cors.allowed-origins=https://example.org
spring.graphql.cors.allowed-methods=GET,POST
spring.graphql.cors.max-age=1800s
spring:
  graphql:
    cors:
      allowed-origins: "https://example.org"
      allowed-methods: GET,POST
      max-age: 1800s

RSocket

RSocket 也作为传输支持,基于 WebSocket 或 TCP。 一旦配置了 RSocket 服务器,我们就可以使用 spring.graphql.rsocket.mapping 在特定路由上配置我们的 GraphQL 处理程序。 例如,将该映射配置为 "graphql" 意味着我们可以在使用 RSocketGraphQlClient 发送请求时将其用作路由。

Spring Boot 自动配置一个 RSocketGraphQlClient.Builder<?> bean,你可以在组件中注入它:

  • Java

  • Kotlin

@Component
public class RSocketGraphQlClientExample {

	private final RSocketGraphQlClient graphQlClient;

	public RSocketGraphQlClientExample(RSocketGraphQlClient.Builder<?> builder) {
		this.graphQlClient = builder.tcp("example.spring.io", 8181).route("graphql").build();
	}
@Component
class RSocketGraphQlClientExample(private val builder: RSocketGraphQlClient.Builder<*>) {

然后发送请求: include-code::RSocketGraphQlClientExample[tag=request]

异常处理

Spring GraphQL 使应用程序能够注册一个或多个 Spring DataFetcherExceptionResolver 组件,这些组件按顺序调用。 异常必须解析为 GraphQLError 对象列表,参见 Spring GraphQL 异常处理文档。 Spring Boot 将自动检测 DataFetcherExceptionResolver bean 并将它们注册到 GraphQlSource.Builder

GraphiQL 和 Schema Printer

Spring GraphQL 提供了基础设施来帮助开发者在消费或开发 GraphQL API 时。

Spring GraphQL 附带一个默认的 GraphiQL 页面,默认暴露在 "/graphiql"。 默认情况下禁用此页面,可以通过 spring.graphql.graphiql.enabled 属性启用。 许多暴露此类页面的应用程序会更喜欢自定义构建。 默认实现在开发过程中非常有用,这就是为什么它在开发过程中通过 spring-boot-devtools 自动暴露。

spring.graphql.schema.printer.enabled 属性启用时,你还可以选择在 /graphql/schema 以文本格式暴露 GraphQL schema。