跳到主要内容

Spring for GraphQL

DeepSeek V3 中英对照 Spring for GraphQL

如果你想构建 GraphQL 应用程序,可以利用 Spring Boot 对 Spring for GraphQL 的自动配置功能。Spring for GraphQL 项目基于 GraphQL Java 实现。你至少需要 spring-boot-starter-graphql 这个启动器。由于 GraphQL 是与传输层无关的,你还需要在应用程序中添加一个或多个额外的启动器,以便通过网络暴露你的 GraphQL API:

启动器传输方式实现方式
spring-boot-starter-webHTTPSpring MVC
spring-boot-starter-websocketWebSocket用于 Servlet 应用程序的 WebSocket
spring-boot-starter-webfluxHTTP, WebSocketSpring WebFlux
spring-boot-starter-rsocketTCP, WebSocket基于 Reactor Netty 的 Spring WebFlux

GraphQL 模式

一个 Spring GraphQL 应用在启动时需要定义模式。默认情况下,你可以在 src/main/resources/graphql/** 目录下编写 ".graphqls" 或 ".gqls" 模式文件,Spring Boot 会自动识别它们。你可以通过 spring.graphql.schema.locations 自定义模式文件的位置,并通过 spring.graphql.schema.file-extensions 自定义文件扩展名。

备注

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

在接下来的部分中,我们将考虑这个示例 GraphQL 模式,它定义了两个类型和两个查询:

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
}
json
备注

默认情况下,字段内省 将在模式上被允许,因为它是诸如 GraphiQL 等工具所必需的。如果你不希望暴露模式的相关信息,可以通过将 spring.graphql.schema.introspection.enabled 设置为 false 来禁用内省功能。

GraphQL 运行时装配

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

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

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 + "!";
}

}
java

Querydsl 和 QueryByExample 仓库支持

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

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

会被 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 提供,其 @Order 值为 0。如果你定义了自己的 RouterFunction bean,可能需要添加适当的 @Order 注解,以确保它们被正确排序。

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

  • 对于 Servlet 应用程序,需要添加 WebSocket 启动器 spring-boot-starter-websocket

  • 对于 WebFlux 应用程序,无需额外依赖

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

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

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

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

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

RSocket

RSocket 也被支持作为一种传输方式,可以在 WebSocket 或 TCP 之上运行。一旦 RSocket 服务器配置完成,我们可以使用 spring.graphql.rsocket.mapping 在特定路由上配置 GraphQL 处理器。例如,将该映射配置为 "graphql" 意味着我们可以在使用 RSocketGraphQlClient 发送请求时将其作为路由。

Spring Boot 会自动配置一个 RSocketGraphQlClient.Builder<?> bean,你可以将其注入到你的组件中:

@Component
public class RSocketGraphQlClientExample {

private final RSocketGraphQlClient graphQlClient;

public RSocketGraphQlClientExample(RSocketGraphQlClient.Builder<?> builder) {
this.graphQlClient = builder.tcp("example.spring.io", 8181).route("graphql").build();
}
java

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

异常处理

Spring GraphQL 允许应用程序注册一个或多个 Spring DataFetcherExceptionResolver 组件,这些组件会被依次调用。异常必须被解析为一系列 GraphQLError 对象,详见 Spring GraphQL 异常处理文档。Spring Boot 会自动检测 DataFetcherExceptionResolver Bean,并将它们注册到 GraphQlSource.Builder 中。

GraphiQL 和 Schema 打印机

Spring GraphQL 提供了基础设施,帮助开发者在消费或开发 GraphQL API 时更加高效。

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

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