请求执行
ExecutionGraphQlService
是调用 GraphQL Java 执行的主要 Spring 抽象
请求。底层传输(如 HTTP)委托给来处理请求。ExecutionGraphQlService
主实现 配置了 用于访问要调用的实例。DefaultExecutionGraphQlService
GraphQlSource
graphql.GraphQL
GraphQLSource
GraphQlSource
是一个 Contract 来公开要使用的实例
包含用于构建该实例的构建器 API。默认生成器可通过 获得。graphql.GraphQL
GraphQlSource.schemaResourceBuilder()
Boot Starter 会创建此构建器的实例并进一步初始化它
要从可配置位置加载 Schema 文件,
公开要应用于的属性,检测 RuntimeWiringConfigurer
bean,用于 GraphQL 指标的插桩 bean,
和 bean 进行异常解决。对于进一步的自定义,您还可以
声明一个 bean,例如:GraphQlSource.Builder
DataFetcherExceptionResolver
SubscriptionExceptionResolver
GraphQlSourceBuilderCustomizer
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class GraphQlConfig {
@Bean
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
return (builder) ->
builder.configureGraphQl((graphQlBuilder) ->
graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
}
}
Schema 资源
GraphQlSource.Builder
可以配置一个或多个实例
解析并合并在一起。这意味着 schema 文件几乎可以从任何
位置。Resource
默认情况下,Boot Starters会查找带有扩展名的 schema 文件
位置下的“.graphqls”或“.gqls”,通常为 .您还可以使用文件系统位置或任何位置
受 Spring 层次结构支持,包括一个自定义实现
从远程位置、存储或内存加载架构文件。classpath:graphql/**
src/main/resources/graphql
Resource
用于跨多个 Classpath 查找 schema 文件
位置,例如跨多个模块。classpath*:graphql/**/ |
Schema 创建
默认情况下,使用 GraphQL Java 创建 .这适用于典型用途,但如果您需要使用
不同的生成器,你可以注册一个回调:GraphQlSource.Builder
SchemaGenerator
graphql.schema.GraphQLSchema
schemaFactory
GraphQlSource.Builder builder = ...
builder.schemaResources(..)
.configureRuntimeWiring(..)
.schemaFactory((typeDefinitionRegistry, runtimeWiring) -> {
// create GraphQLSchema
})
有关如何使用 Spring Boot 进行配置的信息,请参见 GraphQlSource 部分。
如果对联合感兴趣,请参阅 Federation 部分。
RuntimeWiringConfigurer
A 可用于注册以下内容:RuntimeWiringConfigurer
-
自定义标量类型。
-
处理 Directive 的代码。
-
直接注册。
DataFetcher
-
以及更多...
Spring 应用程序通常不需要执行直接注册。
相反,控制器方法通过 注册为 s ,这是一个 .DataFetcher DataFetcher AnnotatedControllerConfigurer RuntimeWiringConfigurer |
GraphQL Java 服务器应用程序仅将 Jackson 用于与数据映射之间的序列化。 客户端输入被解析为 Map。服务器输出将根据字段选择集组装到地图中。 这意味着您不能依赖 Jackson 序列化/反序列化 Comments。 相反,您可以使用自定义标量类型。 |
Boot Starter 检测 type 为
在 .这意味着在大多数情况下,您将拥有
类似于 this 的配置:RuntimeWiringConfigurer
GraphQlSource.Builder
@Configuration
public class GraphQlConfig {
@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer(BookRepository repository) {
GraphQLScalarType scalarType = ... ;
SchemaDirectiveWiring directiveWiring = ... ;
return wiringBuilder -> wiringBuilder
.scalar(scalarType)
.directiveWiring(directiveWiring);
}
}
如果您需要添加 ,例如,进行注册时要考虑
模式定义中,实现同时接受 和 output 的替代方法。这允许您添加任何
然后按顺序调用的工厂数。WiringFactory
configure
RuntimeWiring.Builder
List<WiringFactory>
TypeResolver
GraphQlSource.Builder
registers 作为默认值,用于尚未进行此类注册的 GraphQL 接口和联合
通过 RuntimeWiringConfigurer
。目的
a 用于确定值的 GraphQL 对象类型
从 for a GraphQL Interface 或 Union 字段返回。ClassNameTypeResolver
TypeResolver
TypeResolver
DataFetcher
ClassNameTypeResolver
尝试将值的简单类名与 GraphQL 匹配
Object 类型,如果不成功,它还会导航其超类型,包括
基类和接口,寻找匹配项。 提供了一个
选项来配置名称提取函数以及 GraphQL 对象类型
名称映射应该有助于涵盖更多极端情况:ClassNameTypeResolver
Class
GraphQlSource.Builder builder = ...
ClassNameTypeResolver classNameTypeResolver = new ClassNameTypeResolver();
classNameTypeResolver.setClassNameExtractor((klass) -> {
// Implement Custom ClassName Extractor here
});
builder.defaultTypeResolver(classNameTypeResolver);
有关如何使用 Spring Boot 进行配置的信息,请参见 GraphQlSource 部分。
指令
GraphQL 语言支持“描述替代运行时执行和 GraphQL 文档中的类型验证行为”。指令类似于 Java,但在 GraphQL 文档中的类型、字段、片段和操作上声明。
GraphQL Java 提供了帮助应用程序检测的协定
和 handle 指令。有关更多详细信息,请参阅
GraphQL Java 文档。SchemaDirectiveWiring
在 Spring GraphQL 中,你可以通过RuntimeWiringConfigurer
注册一个。Boot Starter 检测到
这样的 bean,所以你可能会有这样的东西:SchemaDirectiveWiring
@Configuration
public class GraphQlConfig {
@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer() {
return builder -> builder.directiveWiring(new MySchemaDirectiveWiring());
}
}
有关指令支持的示例,请查看 Graphql Java 库的扩展验证。 |
ExecutionStrategy
GraphQL Java 中的一个驱动请求的字段的获取。
要创建 ,您需要提供 .
默认情况下,Spring for GraphQL 会创建要使用的异常处理程序,如 异常 中所述,并将其设置在 .然后,GraphQL Java 使用它来创建具有配置的异常处理程序的实例。ExecutionStrategy
ExecutionStrategy
DataFetcherExceptionHandler
GraphQL.Builder
AsyncExecutionStrategy
如果需要创建自定义 ,可以以相同的方式检测 s 并创建异常处理程序,并使用
it 创建自定义 .例如,在 Spring Boot 应用程序中:ExecutionStrategy
DataFetcherExceptionResolver
ExecutionStrategy
@Bean
GraphQlSourceBuilderCustomizer sourceBuilderCustomizer(
ObjectProvider<DataFetcherExceptionResolver> resolvers) {
DataFetcherExceptionHandler exceptionHandler =
DataFetcherExceptionResolver.createExceptionHandler(resolvers.stream().toList());
AsyncExecutionStrategy strategy = new CustomAsyncExecutionStrategy(exceptionHandler);
return sourceBuilder -> sourceBuilder.configureGraphQl(builder ->
builder.queryExecutionStrategy(strategy).mutationExecutionStrategy(strategy));
}
架构转换
如果要遍历,可以注册一个 via
并在创建架构后对其进行转换,然后对架构进行更改。注意事项
这通常比 Schema Traversal 更昂贵
首选遍历而不是转换,除非您需要进行架构更改。graphql.schema.GraphQLTypeVisitor
builder.schemaResources(..).typeVisitorsToTransformSchema(..)
架构遍历
如果要在
它已创建,并且可能会将更改应用于 .请记住,
但是,此类访客无法更改架构。如果需要更改架构,请参阅 架构转换。graphql.schema.GraphQLTypeVisitor
builder.schemaResources(..).typeVisitors(..)
GraphQLCodeRegistry
Schema 映射检查
如果查询、更改或订阅操作没有 ,则不会
返回任何数据,并且不会执行任何有用的操作。同样,以下 schema 类型的字段
既未通过注册明确覆盖,也未由
default 查找匹配属性时,将始终为 .DataFetcher
DataFetcher
PropertyDataFetcher
Class
null
GraphQL Java 不执行检查以确保覆盖每个架构字段,并且作为
较低级别的库,GraphQL Java 根本不知道 a 可以返回什么
或它所依赖的参数,因此无法执行此类验证。这可以
导致间隙,根据测试覆盖率,这些间隙可能直到运行时才被发现,当
客户端可能会遇到 “silent” 值或非 null 字段错误。DataFetcher
null
Spring for GraphQL 中的接口允许
公开返回类型和预期参数等信息。控制器方法、Querydsl 和 Query by Example 的所有内置 Spring 实现都是此接口的实现。对于带注解的控制器,返回类型和
预期参数基于控制器方法签名。这使得它可能
在启动时检查架构映射,以确保满足以下条件:SelfDescribingDataFetcher
DataFetcher
DataFetcher
-
架构字段具有 registration 或相应的属性。
DataFetcher
Class
-
DataFetcher
registrations 引用存在的架构字段。 -
DataFetcher
参数具有匹配的架构字段参数。
要启用 Schema 检查,请按如下所示进行自定义。
在这种情况下,报告只是记录下来,但您可以选择执行任何操作:GraphQlSource.Builder
GraphQlSource.Builder builder = ...
builder.schemaResources(..)
.inspectSchemaMappings(report -> {
logger.debug(report);
});
示例报表:
GraphQL schema inspection: Unmapped fields: {Book=[title], Author[firstName, lastName]} (1) Unmapped registrations: {Book.reviews=BookController#reviews[1 args]} (2) Unmapped arguments: {BookController#bookSearch[1 args]=[myAuthor]} (3) Skipped types: [BookOrAuthor] (4)
1 | 未以任何方式覆盖的架构字段 |
2 | DataFetcher 对不存在的字段的注册 |
3 | DataFetcher 不存在的预期参数 |
4 | 已跳过的架构类型(接下来将解释) |
在某些情况下,架构类型的类型是未知的。也许没有
implement ,或者声明的返回类型过于通用
(例如 ) 或未知 (例如 ),或者 可能完全缺失。
在这种情况下,架构类型将列为 skipped,因为无法验证。对于每个
skipped 类型,则会显示一条 DEBUG 消息,说明跳过它的原因。Class
DataFetcher
SelfDescribingDataFetcher
Object
List<?>
DataFetcher
联合和接口
对于联合,检查会迭代成员类型并尝试查找相应的 类。对于接口,检查会迭代实现类型和 Look 对于相应的类。
默认情况下,在以下情况下,可以立即检测到相应的 Java 类:
-
的简单名称与接口实现的 GraphQL 联合成员匹配 type name 的 JSON JSON 中,并且 与 controller 方法或控制器类,映射到 union 或 interface 字段。
Class
Class
-
在架构的其他部分进行检查,其中映射字段为 具体的 union 成员或接口实现类型。
Class
-
您已注册具有显式 GraphQL 类型映射的 TypeResolver。
Class
在上述帮助中没有,并且 GraphQL 类型在架构检查中报告为跳过 报告,您可以进行以下自定义:
-
将 GraphQL 类型名称显式映射到一个或多个 Java 类。
-
配置一个函数,用于自定义 GraphQL 类型名称如何适应简单名称。这有助于满足特定的 Java 类命名约定。
Class
-
提供 a 以映射 GraphQL 类型 a Java 类。
ClassNameTypeResolver
例如:
GraphQlSource.Builder builder = ...
builder.schemaResources(..)
.inspectSchemaMappings(
initializer -> initializer.classMapping("Author", Author.class)
logger::debug);
Operation Caching
GraphQL Java 必须在执行操作之前对其进行解析和验证。这可能会影响
性能显着。为避免需要重新分析和验证,应用程序可以
配置 a 来缓存和重用 Document 实例。GraphQL Java 文档提供了有关以下内容的更多详细信息
查询缓存。PreparsedDocumentProvider
PreparsedDocumentProvider
在 Spring GraphQL 中,您可以通过:
.PreparsedDocumentProvider
GraphQlSource.Builder#configureGraphQl
// Typically, accessed through Spring Boot's GraphQlSourceBuilderCustomizer
GraphQlSource.Builder builder = ...
// Create provider
PreparsedDocumentProvider provider =
new ApolloPersistedQuerySupport(new InMemoryPersistedQueryCache(Collections.emptyMap()));
builder.schemaResources(..)
.configureRuntimeWiring(..)
.configureGraphQl(graphQLBuilder -> graphQLBuilder.preparsedDocumentProvider(provider))
有关如何使用 Spring Boot 进行配置的信息,请参见 GraphQlSource 部分。
螺纹模型
大多数 GraphQL 请求都受益于获取嵌套字段的并发执行。这是
为什么现在大多数应用程序都依赖于 GraphQL Java 的 ,它允许
数据获取器返回并发执行,而不是串行执行。AsyncExecutionStrategy
CompletionStage
Java 21 和虚拟线程增加了一个重要的功能,可以有效地使用更多线程,但是 仍然需要并发执行,而不是串行执行,以便请求 执行以更快地完成。
Spring for GraphQL 支持:
-
响应式数据获取器,它们是 如 预期的那样适应了 。
CompletionStage
AsyncExecutionStrategy
-
CompletionStage
作为返回值。 -
Controller 方法,即 Kotlin 协程方法。
-
@SchemaMapping 和 @BatchMapping 方法可以返回提交到 Spring Framework 等的 。要启用此功能,您必须在 .
Callable
Executor
VirtualThreadTaskExecutor
Executor
AnnotatedControllerConfigurer
Spring for GraphQL 在 Spring MVC 或 WebFlux 上运行作为传输。Spring MVC
使用异步请求执行,除非结果已完成
在 GraphQL Java 引擎返回后立即返回,如果
request 足够简单,不需要异步数据获取。CompletableFuture
反应性的DataFetcher
默认构建器支持返回 a 或将其调整为 where 值聚合
并转换为 List,除非请求是 GraphQL 订阅请求,
在这种情况下,返回值仍然是用于流式处理的 Reactive Streams
GraphQL 响应。GraphQlSource
DataFetcher
Mono
Flux
CompletableFuture
Flux
Publisher
响应式可以依赖从
传输层,例如从 WebFlux 请求处理,请参阅 WebFlux 上下文。DataFetcher
对于订阅请求,GraphQL Java 将在项目
可用,并且已获取其请求的所有字段。因为这涉及几个
层异步数据获取,项目可能会通过网络从其
原始订单。如果您希望 GraphQL Java 缓冲项目并保留原始顺序,
您可以通过在 .例如,可以使用自定义 :SubscriptionExecutionStrategy.KEEP_SUBSCRIPTION_EVENTS_ORDERED
GraphQLContext
Instrumentation
import graphql.ExecutionResult;
import graphql.execution.SubscriptionExecutionStrategy;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.InstrumentationState;
import graphql.execution.instrumentation.SimpleInstrumentationContext;
import graphql.execution.instrumentation.SimplePerformantInstrumentation;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class GraphQlConfig {
@Bean
public SubscriptionOrderInstrumentation subscriptionOrderInstrumentation() {
return new SubscriptionOrderInstrumentation();
}
static class SubscriptionOrderInstrumentation extends SimplePerformantInstrumentation {
@Override
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters,
InstrumentationState state) {
// Enable option for keeping subscription results in upstream order
parameters.getGraphQLContext().put(SubscriptionExecutionStrategy.KEEP_SUBSCRIPTION_EVENTS_ORDERED, true);
return SimpleInstrumentationContext.noOp();
}
}
}
上下文传播
Spring for GraphQL 支持通过 GraphQL Java 透明地从 HTTP 传输传播上下文,并传播到它调用的其他组件。这包括上下文
来自 Spring MVC 请求处理线程和 WebFlux 的 Reactor
处理管道。DataFetcher
ThreadLocal
Context
WebMvc 网络
GraphQL Java 调用的 A 和其他组件可能并不总是在
与 Spring MVC 处理程序相同的线程,例如,如果异步 WebGraphQlInterceptor
或切换到
不同的线程。DataFetcher
DataFetcher
Spring for GraphQL 支持从 Servlet 容器传播值
线程添加到线程 a 和其他组件中,GraphQL Java 调用到
执行时间。为此,应用程序需要实现感兴趣的值:ThreadLocal
DataFetcher
io.micrometer.context.ThreadLocalAccessor
ThreadLocal
public class RequestAttributesAccessor implements ThreadLocalAccessor<RequestAttributes> {
@Override
public Object key() {
return RequestAttributesAccessor.class.getName();
}
@Override
public RequestAttributes getValue() {
return RequestContextHolder.getRequestAttributes();
}
@Override
public void setValue(RequestAttributes attributes) {
RequestContextHolder.setRequestAttributes(attributes);
}
@Override
public void reset() {
RequestContextHolder.resetRequestAttributes();
}
}
您可以在启动时手动注册 全局实例,该实例可通过 访问。您也可以注册它
自动通过该机构。ThreadLocalAccessor
ContextRegistry
io.micrometer.context.ContextRegistry#getInstance()
java.util.ServiceLoader
WebFlux的
响应式 DataFetcher
可以依赖于对 Reactor 上下文的访问,该上下文
源自 WebFlux 请求处理链。这包括 Reactor 上下文
由 WebGraphQlInterceptor 组件添加。
异常
在 GraphQL Java 中,决定如何表示
在响应的 “errors” 部分中获取数据。应用程序可以注册
仅限单个处理程序。DataFetcherExceptionHandler
Spring for GraphQL 注册一个提供默认
处理并启用合约。应用程序可以
通过 GraphQLSource
构建器注册任意数量的解析程序,这些解析程序位于
order 直到一个他们解决 到 a .
Spring Boot Starters检测这种类型的 bean。DataFetcherExceptionHandler
DataFetcherExceptionResolver
Exception
List<graphql.GraphQLError>
DataFetcherExceptionResolverAdapter
是一个方便的基类,其中包含受保护的方法 和 .resolveToSingleError
resolveToMultipleErrors
带注释的控制器编程模型允许使用
具有灵活方法签名的带注释的异常处理程序方法,有关详细信息,请参阅 @GraphQlExceptionHandler
。
A 可以根据 GraphQL Java 或 Spring GraphQL 分配给类别,它定义了以下内容:GraphQLError
graphql.ErrorClassification
ErrorType
-
BAD_REQUEST
-
UNAUTHORIZED
-
FORBIDDEN
-
NOT_FOUND
-
INTERNAL_ERROR
如果异常仍未解决,则默认情况下,该异常被归类为包含类别名称和 from 的通用消息。该消息故意不透明以避免泄漏
实现细节。应用程序可以使用 进行自定义
错误详细信息。INTERNAL_ERROR
executionId
DataFetchingEnvironment
DataFetcherExceptionResolver
未解决的异常将记录在 ERROR 级别以及 to correlate
发送到客户端的错误。已解决的异常记录在 DEBUG 级别。executionId
请求例外
GraphQL Java 引擎在解析请求时可能会遇到验证或其他错误
这反过来又会阻止请求执行。在这种情况下,响应包含
“data” 键,以及一个或多个请求级别的 “错误”,这些错误是全局的,即不是
具有字段路径。null
DataFetcherExceptionResolver
无法处理此类全局错误,因为它们是引发的
在执行开始之前和调用 any 之前。应用程序可以使用
传输级拦截器来检查和转换 .
请参阅 WebGraphQlInterceptor
下的示例。DataFetcher
ExecutionResult
包年包月例外
的 for a subscription 请求可能会完成并显示错误信号,在这种情况下
底层传输(例如 WebSocket)发送带有列表的最终 “error” 类型消息
的 GraphQL 错误。Publisher
DataFetcherExceptionResolver
无法解决订阅 中的错误
由于数据仅创建初始。之后,
transport 订阅 ,然后可能会完成并显示错误。Publisher
DataFetcher
Publisher
Publisher
应用程序可以注册 a 以解析
exceptions 来解决这些问题为 GraphQL 错误
以发送到客户端。SubscriptionExceptionResolver
Publisher
分页
GraphQL 游标连接规范定义了一种导航大型结果集的方法,方法是一次返回 每个项目都与一个游标配对,客户端可以使用该游标来请求更多项目 或在引用的项之后。
该规范将此模式称为 “Connections”,名称以
with 是表示分页结果集的连接类型。
所有连接类型都包含一个名为 “edges” 的字段,其中类型包含
实际项目、光标和一个名为 “pageInfo” 的字段,该字段指示如果
项存在 forward 和 backward。~Connection
~Edge
连接类型
连接类型需要样板定义,Spring for GraphQL 可以在启动时透明地添加这些定义,即使没有明确添加
宣布。这意味着您只需要以下内容,连接和边缘类型将
为您添加:ConnectionTypeDefinitionConfigurer
Query {
books(first:Int, after:String, last:Int, before:String): BookConnection
}
type Book {
id: ID!
title: String!
}
正向分页定义的 spec 和参数允许客户端
请求给定游标“之后”的“第一个”N 项。同样,用于向后分页参数的 and 参数允许请求 “before” 的 “last” N 项
给定的游标。first
after
last
before
该规范不鼓励同时包括 and,并且还说明了结果
因为分页变得不清楚。在 Spring for GraphQL 中,如果存在 或 存在,
then 和 被忽略。first last first after last before |
要生成连接类型,请按如下方式进行配置:ConnectionTypeDefinitionConfigurer
GraphQlSource.schemaResourceBuilder()
.schemaResources(..)
.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer)
上面将添加以下类型定义:
type BookConnection {
edges: [BookEdge]!
pageInfo: PageInfo!
}
type BookEdge {
node: Book!
cursor: String!
}
type PageInfo {
hasPreviousPage: Boolean!
hasNextPage: Boolean!
startCursor: String
endCursor: String
}
默认情况下,Boot Starter 会注册。ConnectionTypeDefinitionConfigurer
ConnectionAdapter
除了架构中的连接类型之外,
您还需要等效的 Java 类型。GraphQL Java 提供了这些参数,包括泛型和类型,以及 .Connection
Edge
PageInfo
您可以从控制器方法返回,但它需要样板代码
使底层数据分页机制适应 ,以创建游标,
添加包装器,并创建一个 .Connection
Connection
~Edge
PageInfo
Spring for GraphQL 定义了适应项目容器的协定
自。适配器是从
由 .您可以按如下方式对其进行配置:ConnectionAdapter
Connection
DataFetcher
ConnectionFieldTypeVisitor
ConnectionAdapter adapter = ... ;
GraphQLTypeVisitor visitor = ConnectionFieldTypeVisitor.create(List.of(adapter)) (1)
GraphQlSource.schemaResourceBuilder()
.schemaResources(..)
.typeDefinitionConfigurer(..)
.typeVisitors(List.of(visitor)) (2)
1 | 创建具有一个或多个 s 的 type visitor 。ConnectionAdapter |
2 | 抵制类型的访客。 |
有内置的 s
对于 Spring Data 和 .您还可以创建自己的自定义适配器。 实现依赖于 CursorStrategy
来
为返回的项目创建游标。相同的策略也用于支持 Subrange
控制器方法
参数。ConnectionAdapter
Window
Slice
ConnectionAdapter
CursorStrategy
CursorStrategy
是一个合约,用于对引用
项在大型结果集中的位置。游标可以基于索引或
在键集上。
ConnectionAdapter
使用它来对返回的 items 的游标进行编码。带注释的 Controllers 方法、Querydsl 存储库和 Query by Example 存储库使用它来解码分页请求中的游标,并创建一个 .Subrange
CursorEncoder
是一个相关的合约,它进一步编码和解码 String 游标为
使它们对客户不透明。 与 .您可以使用 ,也可以创建自己的 。EncodingCursorStrategy
CursorStrategy
CursorEncoder
Base64CursorEncoder
NoOpEncoder
Spring Data 有一个内置的 。当 Spring Data 存在时,Boot Starter 会注册一个 with。CursorStrategy
ScrollPosition
CursorStrategy<ScrollPosition>
Base64Encoder
排序
在 GraphQL 请求中没有提供排序信息的标准方法。然而 分页取决于稳定的排序顺序。您可以使用默认订单,或者其他方式 公开输入类型并从 GraphQL 参数中提取排序详细信息。
内置了对 Spring Data 作为控制器的支持
method 参数。要使其正常工作,您需要有一个 bean。Sort
SortStrategy
批量加载
给定 a 及其 ,我们可以为一本书创建一个 和 另一个
对于它的作者。这允许选择有作者或无作者的书籍,但这意味着书籍
和 authors 不会一起加载,这在查询多个
books 作为每本书的作者是单独加载的。这称为 N+1 选择
问题。Book
Author
DataFetcher
DataLoader
GraphQL Java 提供了一种批量加载相关实体的机制。
您可以在 GraphQL Java 文档中找到完整的详细信息。下面是一个
工作原理摘要:DataLoader
-
Register 的 ,可以加载实体,给定唯一键。
DataLoader
DataLoaderRegistry
-
DataFetcher
可以访问 并使用它们按 ID 加载实体。DataLoader
-
A 通过返回 future 来延迟加载,以便可以批量完成。
DataLoader
-
DataLoader
维护加载实体的每个请求缓存,该缓存可以进一步 提高效率。
BatchLoaderRegistry
GraphQL Java 中的完整批处理加载机制需要实现以下之一
several 接口,然后将它们包装并注册为 S
名称位于 .BatchLoader
DataLoader
DataLoaderRegistry
Spring GraphQL 中的 API 略有不同。对于注册,只有一个
Central 公开工厂方法和用于 create 和
注册任意数量的批量加载函数:BatchLoaderRegistry
@Configuration
public class MyConfig {
public MyConfig(BatchLoaderRegistry registry) {
registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
// return Mono<Map<Long, Author>
});
// more registrations ...
}
}
Boot Starter 声明了一个可以注入的 bean
您的配置,如上所示,或按顺序放入任何组件(如控制器)
注册批量加载函数。反过来,它被注入到确保每个请求的注册的位置。BatchLoaderRegistry
BatchLoaderRegistry
DefaultExecutionGraphQlService
DataLoader
默认情况下,该名称基于目标实体的类名。
这允许方法使用泛型类型声明 DataLoader 参数,并且
无需指定名称。但是,如有必要,可以通过生成器自定义名称以及其他 .DataLoader
@SchemaMapping
BatchLoaderRegistry
DataLoaderOptions
要全局配置 default,要用作任何
registration,你可以覆盖 Boot 的 bean 并使用构造函数
因为接受 .DataLoaderOptions
BatchLoaderRegistry
DefaultBatchLoaderRegistry
Supplier<DataLoaderOptions>
在许多情况下,在加载相关实体时,您可以使用 @BatchMapping 控制器方法,这是一种快捷方式
for 和 replace 需要使用 和 直接。BatchLoaderRegistry
DataLoader
BatchLoaderRegistry
还提供其他重要的好处。它支持访问
与 batch loading 函数和 from 方法相同,
以及确保对它们的上下文传播。这就是预期应用的原因
以使用它。可以直接执行自己的注册,但
此类注册将放弃上述好处。GraphQLContext
@BatchMapping
DataLoader
测试 Batch Loading
首先在 上执行注册 :BatchLoaderRegistry
DataLoaderRegistry
BatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();
// perform registrations...
DataLoaderRegistry dataLoaderRegistry = DataLoaderRegistry.newRegistry().build();
batchLoaderRegistry.registerDataLoaders(dataLoaderRegistry, graphQLContext);
现在,您可以按如下方式访问和测试单个 :DataLoader
DataLoader<Long, Book> loader = dataLoaderRegistry.getDataLoader(Book.class.getName());
loader.load(1L);
loader.loadMany(Arrays.asList(2L, 3L));
List<Book> books = loader.dispatchAndJoin(); // actual loading
assertThat(books).hasSize(3);
assertThat(books.get(0).getName()).isEqualTo("...");
// ...