Spring for GraphQL

如果你想构建 GraphQL 应用,你可以利用 Spring Boot 对 Spring for GraphQL 的自动配置。Spring for GraphQL 项目基于 GraphQL Java。你至少需要 `spring-boot-starter-graphql` 启动器。因为 GraphQL 与传输无关,你还需要在你的应用中添加一个或多个启动器来通过 Web 暴露你的 GraphQL API。

启动器 传输 实现

spring-boot-starter-web

HTTP

Spring MVC

spring-boot-starter-websocket

WebSocket

Servlet 应用的 WebSocket

spring-boot-starter-webflux

HTTP, WebSocket

Spring WebFlux

spring-boot-starter-rsocket

TCP, WebSocket

基于 Reactor Netty 的 Spring WebFlux

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
}
默认情况下,字段内省 将被允许在 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 仓库支持

Spring Data 支持 Querydsl 和 QueryByExample 仓库。Spring GraphQL 可以将 Querydsl 和 QueryByExample 仓库配置为DataFetcher

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

  • QuerydslPredicateExecutor

  • ReactiveQuerydslPredicateExecutor

  • QueryByExampleExecutor

  • ReactiveQueryByExampleExecutor

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

传输

HTTP 和 WebSocket

GraphQL HTTP 端点默认位于 HTTP POST /graphql。它还支持仅用于订阅的服务器发送事件的"text/event-stream"媒体类型。路径可以使用spring.graphql.path自定义。

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

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

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

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

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

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

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

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

  • 属性

  • 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 组件,这些组件按顺序调用。必须将异常解析为graphql.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 Schema。