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 |
---|---|---|
|
HTTP |
Spring MVC |
|
WebSocket |
WebSocket for Servlet apps |
|
HTTP, WebSocket |
Spring WebFlux |
|
TCP, WebSocket |
Spring WebFlux on Reactor Netty |
GraphQL Schema
Spring GraphQL 应用在启动时需要定义 schema。
默认情况下,你可以将 ".graphqls" 或 ".gqls" schema 文件放在 src/main/resources/graphql/**
下,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
。
以下是 greeting 查询的一个 @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 仓库:
会被 Spring Boot 检测为顶层查询的 DataFetcher
候选。
传输方式
HTTP 与 WebSocket
GraphQL HTTP 端点默认位于 HTTP POST /graphql
。
同时支持通过 Server Sent Events 订阅的 "text/event-stream" 媒体类型。
路径可通过 spring.graphql.http.path
自定义。
Spring MVC 和 Spring WebFlux 的 HTTP 端点均由 @Order 为 0 的 RouterFunction bean 提供。
如你自定义了 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 MVC 和 Spring WebFlux 支持 CORS(跨域资源共享)请求。 CORS 是通过不同域访问的 GraphQL 应用 web 配置中的关键部分。
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 打印
Spring GraphQL 提供了便于开发者消费或开发 GraphQL API 的基础设施。
Spring GraphQL 默认自带 GraphiQL 页面,默认暴露在 "/graphiql"
。
该页面默认关闭,可通过 spring.graphql.graphiql.enabled
属性开启。
许多应用更倾向于自定义页面,默认实现非常适合开发阶段,因此在开发时会通过 spring-boot-devtools
自动暴露。
你还可以在启用 spring.graphql.schema.printer.enabled
属性时,将 GraphQL schema 以文本格式暴露在 /graphql/schema
。