|
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring GraphQL 1.3.2! |
|
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring GraphQL 1.3.2! |
ExecutionGraphQlService是调用 GraphQL Java 执行的主要 Spring 抽象
请求。底层传输(如 HTTP)委托给来处理请求。ExecutionGraphQlService
主实现 配置了 用于访问要调用的实例。DefaultExecutionGraphQlServiceGraphQlSourcegraphql.GraphQL
GraphQLSource
GraphQlSource是一个 Contract 来公开要使用的实例
包含用于构建该实例的构建器 API。默认生成器可通过 获得。graphql.GraphQLGraphQlSource.schemaResourceBuilder()
Boot Starter 会创建此构建器的实例并进一步初始化它
要从可配置位置加载 Schema 文件,
公开要应用于的属性,检测 RuntimeWiringConfigurer bean,用于 GraphQL 指标的插桩 bean,
和 bean 进行异常解决。对于进一步的自定义,您还可以
声明一个 bean,例如:GraphQlSource.BuilderDataFetcherExceptionResolverSubscriptionExceptionResolverGraphQlSourceBuilderCustomizer
@Configuration(proxyBeanMethods = false)
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/graphqlResource
用于跨多个 Classpath 查找 schema 文件
位置,例如跨多个模块。classpath*:graphql/**/ |
Schema 创建
默认情况下,使用 GraphQL Java 创建 .这适用于典型用途,但如果您需要使用
不同的生成器,例如对于 federation,你可以注册一个回调:GraphQlSource.BuilderSchemaGeneratorgraphql.schema.GraphQLSchemaschemaFactory
GraphQlSource.Builder builder = ...
builder.schemaResources(..)
.configureRuntimeWiring(..)
.schemaFactory((typeDefinitionRegistry, runtimeWiring) -> {
// create GraphQLSchema
})
GraphQlSource 部分解释了如何使用 Spring Boot 进行配置。
有关 Apollo Federation 的示例,请参见 federation-jvm-spring-example。
RuntimeWiringConfigurer
您可以使用以下方法进行注册:RuntimeWiringConfigurer
-
自定义标量类型。
-
interface 和 union 类型的默认
TypeResolver。 -
DataFetcher对于字段,尽管应用程序通常会使用带注释的控制器,并且 这些被检测并注册为 S , 这是一个 .Boot Starter 会自动注册 。DataFetcherAnnotatedControllerConfigurerRuntimeWiringConfigurerAnnotatedControllerConfigurer
| GraphQL Java 服务器应用程序仅将 Jackson 用于与数据映射之间的序列化。 客户端输入被解析为 Map。服务器输出将根据字段选择集组装到地图中。 这意味着您不能依赖 Jackson 序列化/反序列化 Comments。 相反,您可以使用自定义标量类型。 |
Boot Starter 检测 type 为
在 .这意味着在大多数情况下,您将拥有
类似于 this 的配置:RuntimeWiringConfigurerGraphQlSource.Builder
@Configuration
public class GraphQlConfig {
@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer(BookRepository repository) {
GraphQLScalarType scalarType = ... ;
SchemaDirectiveWiring directiveWiring = ... ;
DataFetcher dataFetcher = QuerydslDataFetcher.builder(repository).single();
return wiringBuilder -> wiringBuilder
.scalar(scalarType)
.directiveWiring(directiveWiring)
.type("Query", builder -> builder.dataFetcher("book", dataFetcher));
}
}
如果您需要添加 ,例如,进行注册时要考虑
模式定义中,实现同时接受 和 output 的替代方法。这允许您添加任何
然后按顺序调用的工厂数。WiringFactoryconfigureRuntimeWiring.BuilderList<WiringFactory>
TypeResolver
GraphQlSource.Builderregisters 作为默认值,用于尚未进行此类注册的 GraphQL 接口和联合
通过 RuntimeWiringConfigurer。目的
a 用于确定值的 GraphQL 对象类型
从 for a GraphQL Interface 或 Union 字段返回。ClassNameTypeResolverTypeResolverTypeResolverDataFetcher
ClassNameTypeResolver尝试将值的简单类名与 GraphQL 匹配
Object 类型,如果不成功,它还会导航其超类型,包括
基类和接口,寻找匹配项。 提供了一个
选项来配置名称提取函数以及 GraphQL 对象类型
名称映射应该有助于涵盖更多极端情况:ClassNameTypeResolverClass
GraphQlSource.Builder builder = ...
ClassNameTypeResolver classNameTypeResolver = new ClassNameTypeResolver();
classNameTypeResolver.setClassNameExtractor((klass) -> {
// Implement Custom ClassName Extractor here
});
builder.defaultTypeResolver(classNameTypeResolver);
GraphQlSource 部分解释了如何使用 Spring Boot 进行配置。
指令
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 使用它来创建具有配置的异常处理程序的实例。ExecutionStrategyExecutionStrategyDataFetcherExceptionHandlerGraphQL.BuilderAsyncExecutionStrategy
如果需要创建自定义 ,可以以相同的方式检测 s 并创建异常处理程序,并使用
it 创建自定义 .例如,在 Spring Boot 应用程序中:ExecutionStrategyDataFetcherExceptionResolverExecutionStrategy
@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.GraphQLTypeVisitorbuilder.schemaResources(..).typeVisitorsToTransformSchema(..)
架构遍历
如果要在
它已创建,并且可能会将更改应用于 .请记住,
但是,此类访客无法更改架构。如果需要更改架构,请参阅 架构转换。graphql.schema.GraphQLTypeVisitorbuilder.schemaResources(..).typeVisitors(..)GraphQLCodeRegistry
Schema 映射检查
如果查询、更改或订阅操作没有 ,则不会
返回任何数据,并且不会执行任何有用的操作。同样,返回的架构类型的字段
通过一个操作,该操作既未通过 registration 显式覆盖,也未隐式由 default 覆盖,该操作查找
匹配的 Java 对象属性将始终为 。DataFetcherDataFetcherPropertyDataFetchernull
GraphQL Java 不执行检查以确保覆盖每个架构字段,并且
可能会导致可能无法发现的差距,具体取决于测试覆盖率。在运行时
如果字段不可为空,则可能会收到 “silent” 或 error。作为较低级别
库,GraphQL Java 对实现和
它们的返回类型,因此无法将架构类型结构与 Java 对象进行比较
结构。nullDataFetcher
Spring for GraphQL 定义了允许 公开返回类型信息的接口。所有 Spring 实现
实现此接口。这包括用于 Annotated Controllers 的那些,以及用于 Querydsl 和 Query by Example Spring Data 存储库的那些。对于带注释的
controllers 的 Controllers,则返回类型派生自方法上声明的返回类型。SelfDescribingDataFetcherDataFetcherDataFetcher@SchemaMapping
在启动时,Spring for GraphQL 可以检查架构字段、注册、
以及从实现返回的 Java 对象的属性
如果所有架构字段都由显式注册的 或
匹配的 Java 对象属性。检查还会执行反向检查,以查找针对不存在的架构字段的注册。DataFetcherDataFetcherDataFetcherDataFetcher
要启用架构映射检查,请执行以下操作:
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)
Skipped types: [BookOrAuthor] (3)
| 1 | 未映射的架构字段及其源类型的列表 |
| 2 | 不存在的字段上的注册列表DataFetcher |
| 3 | 跳过的架构类型列表,如下所述 |
架构字段检查可以执行的操作是有限的,尤其是当存在
Java 类型信息不足。如果带注释的控制器方法是
declared to return ,或者如果返回类型具有未指定的泛型
参数(如 ,或者如果 未实现且返回类型甚至未知)。在这种情况下,
Java 对象类型结构仍然未知,并且架构类型在
生成的报告。对于每个跳过的类型,都会记录一条 DEBUG 消息以说明原因
它被跳过了。java.lang.ObjectList<?>DataFetcherSelfDescribingDataFetcher
架构联合类型总是被跳过,因为控制器方法无法 在 Java 中声明这样的返回类型,Java 类型结构是未知的。
架构接口类型仅支持直接声明的字段,这些字段是
与由 .
不检查具体实现上的其他字段。这有待改进
在将来的发行版中,还要检查 Schema 实现类型并尝试
在声明的 Java 返回类型的子类型之间查找匹配项。SelfDescribingDataFetcherinterface
Operation Caching
GraphQL Java 必须在执行操作之前对其进行解析和验证。这可能会影响
性能显着。为避免需要重新分析和验证,应用程序可以
配置 a 来缓存和重用 Document 实例。GraphQL Java 文档提供了有关以下内容的更多详细信息
查询缓存。PreparsedDocumentProviderPreparsedDocumentProvider
在 Spring GraphQL 中,您可以通过:
.PreparsedDocumentProviderGraphQlSource.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))
GraphQlSource 部分解释了如何使用 Spring Boot 进行配置。
用于跨多个 Classpath 查找 schema 文件
位置,例如跨多个模块。classpath*:graphql/**/ |
| GraphQL Java 服务器应用程序仅将 Jackson 用于与数据映射之间的序列化。 客户端输入被解析为 Map。服务器输出将根据字段选择集组装到地图中。 这意味着您不能依赖 Jackson 序列化/反序列化 Comments。 相反,您可以使用自定义标量类型。 |
| 有关指令支持的示例,请查看 Graphql Java 库的扩展验证。 |
| 1 | 未映射的架构字段及其源类型的列表 |
| 2 | 不存在的字段上的注册列表DataFetcher |
| 3 | 跳过的架构类型列表,如下所述 |
螺纹模型
大多数 GraphQL 请求都受益于获取嵌套字段的并发执行。这是
为什么现在大多数应用程序都依赖于 GraphQL Java 的 ,它允许
数据获取器返回并发执行,而不是串行执行。AsyncExecutionStrategyCompletionStage
Java 21 和虚拟线程增加了一个重要的功能,可以有效地使用更多线程,但是 仍然需要并发执行,而不是串行执行,以便请求 执行以更快地完成。
Spring for GraphQL 支持:
-
响应式数据获取器,它们是 如 预期的那样适应了 。
CompletionStageAsyncExecutionStrategy -
CompletionStage作为返回值。 -
Controller 方法,即 Kotlin 协程方法。
-
@SchemaMapping 和 @BatchMapping 方法可以返回提交到 Spring Framework 等的 。要启用此功能,您必须在 .
CallableExecutorVirtualThreadTaskExecutorExecutorAnnotatedControllerConfigurer
Spring for GraphQL 在 Spring MVC 或 WebFlux 上运行作为传输。Spring MVC
使用异步请求执行,除非结果已完成
在 GraphQL Java 引擎返回后立即返回,如果
request 足够简单,不需要异步数据获取。CompletableFuture
反应性的DataFetcher
默认构建器支持返回 a 或将其调整为 where 值聚合
并转换为 List,除非请求是 GraphQL 订阅请求,
在这种情况下,返回值仍然是用于流式处理的 Reactive Streams
GraphQL 响应。GraphQlSourceDataFetcherMonoFluxCompletableFutureFluxPublisher
响应式可以依赖从
传输层,例如从 WebFlux 请求处理,请参阅 WebFlux 上下文。DataFetcher
上下文传播
Spring for GraphQL 支持通过 GraphQL Java 透明地从 HTTP 传输传播上下文,并传播到它调用的其他组件。这包括上下文
来自 Spring MVC 请求处理线程和 WebFlux 的 Reactor
处理管道。DataFetcherThreadLocalContext
WebMvc 网络
GraphQL Java 调用的 A 和其他组件可能并不总是在
与 Spring MVC 处理程序相同的线程,例如,如果异步 WebGraphQlInterceptor 或切换到
不同的线程。DataFetcherDataFetcher
Spring for GraphQL 支持从 Servlet 容器传播值
线程添加到线程 a 和其他组件中,GraphQL Java 调用到
执行时间。为此,应用程序需要实现感兴趣的值:ThreadLocalDataFetcherio.micrometer.context.ThreadLocalAccessorThreadLocal
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();
}
}
您可以在启动时手动注册 全局实例,该实例可通过 访问。您也可以注册它
自动通过该机构。ThreadLocalAccessorContextRegistryio.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。DataFetcherExceptionHandlerDataFetcherExceptionResolverExceptionList<graphql.GraphQLError>
DataFetcherExceptionResolverAdapter是一个方便的基类,其中包含受保护的方法 和 .resolveToSingleErrorresolveToMultipleErrors
带注释的控制器编程模型允许使用
具有灵活方法签名的带注释的异常处理程序方法,有关详细信息,请参阅 @GraphQlExceptionHandler。
A 可以根据 GraphQL Java 或 Spring GraphQL 分配给类别,它定义了以下内容:GraphQLErrorgraphql.ErrorClassificationErrorType
-
BAD_REQUEST -
UNAUTHORIZED -
FORBIDDEN -
NOT_FOUND -
INTERNAL_ERROR
如果异常仍未解决,则默认情况下,该异常被归类为包含类别名称和 from 的通用消息。该消息故意不透明以避免泄漏
实现细节。应用程序可以使用 进行自定义
错误详细信息。INTERNAL_ERRORexecutionIdDataFetchingEnvironmentDataFetcherExceptionResolver
未解决的异常将记录在 ERROR 级别以及 to correlate
发送到客户端的错误。已解决的异常记录在 DEBUG 级别。executionId
请求例外
GraphQL Java 引擎在解析请求时可能会遇到验证或其他错误
这反过来又会阻止请求执行。在这种情况下,响应包含
“data” 键,以及一个或多个请求级别的 “错误”,这些错误是全局的,即不是
具有字段路径。null
DataFetcherExceptionResolver无法处理此类全局错误,因为它们是引发的
在执行开始之前和调用 any 之前。应用程序可以使用
传输级拦截器来检查和转换 .
请参阅 WebGraphQlInterceptor 下的示例。DataFetcherExecutionResult
包年包月例外
的 for a subscription 请求可能会完成并显示错误信号,在这种情况下
底层传输(例如 WebSocket)发送带有列表的最终 “error” 类型消息
的 GraphQL 错误。Publisher
DataFetcherExceptionResolver无法解决订阅 中的错误
由于数据仅创建初始。之后,
transport 订阅 ,然后可能会完成并显示错误。PublisherDataFetcherPublisherPublisher
应用程序可以注册 a 以解析
exceptions 来解决这些问题为 GraphQL 错误
以发送到客户端。SubscriptionExceptionResolverPublisher
分页
GraphQL 游标连接规范定义了一种导航大型结果集的方法,方法是在以下时间返回项目子集 每个项目都与一个游标配对,客户端可以使用该游标在 或 在被引用项之后。
该规范将模式称为 “连接”。名称以
on Connection 是表示分页结果集的 Connection Type。所有类型都包含一个 “edges” 字段,其中 type 将实际项与游标配对,如
以及带有布尔标志的 “pageInfo” 字段,用于指示是否有更多项目转发
和向后。~Connection~Edge
连接类型
Connection必须为每个需要分页的类型创建类型定义,添加
样板和干扰添加到架构中。Spring for GraphQL 允许在启动时添加这些类型(如果尚未添加)
存在于解析的架构文件中。这意味着在 schema 中,您只需要:ConnectionTypeDefinitionConfigurer
Query {
books(first:Int, after:String, last:Int, before:String): BookConnection
}
type Book {
id: ID!
title: String!
}
请注意 spec 定义的前向分页参数,并且客户端可以使用
请求给定游标之后的前 N 项,while 和 are backward
pagination 参数来请求给定游标之前的最后 N 项。firstafterlastbefore
接下来,按如下方式进行配置:ConnectionTypeDefinitionConfigurer
GraphQlSource.schemaResourceBuilder()
.schemaResources(..)
.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer)
以下类型定义将透明地添加到 schema 中:
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
一旦 Connection Types 在 schema 中可用,您还需要
等效的 Java 类型。GraphQL Java 提供了这些选项,包括泛型 和 ,以及 .ConnectionEdgePageInfo
一种选择是填充 a 并从控制器方法 或 .但是,这需要样板代码来创建 ,
创建游标,将每个项目包装为 ,并创建 .
此外,您可能已经有一个底层的分页机制,例如在使用
Spring Data 存储库。ConnectionDataFetcherConnectionEdgePageInfo
Spring for GraphQL 定义了适应项目容器的协定
自。适配器是通过一个装饰器应用的,而这个装饰器又是
通过 安装 .您可以按如下方式对其进行配置:ConnectionAdapterConnectionDataFetcherConnectionFieldTypeVisitor
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 | 抵制类型的访客。 |
Spring Data 和 有内置的 s。您还可以创建自己的自定义适配器。 实现依赖于 CursorStrategy 来
为返回的项目创建游标。相同的策略也用于支持 Subrange 控制器方法参数,该参数包含
pagination input 的 API 中。ConnectionAdapterWindowSliceConnectionAdapter
CursorStrategy
CursorStrategy是一个合约,用于对引用
项在大型结果集中的位置。游标可以基于索引或
在键集上。
ConnectionAdapter 使用它来对返回的 items 的游标进行编码。带注释的 Controllers 方法、Querydsl 存储库和 Query by Example 存储库使用它来解码分页请求中的游标,并创建一个 .Subrange
CursorEncoder是一个相关的合约,它进一步编码和解码 String 游标为
使它们对客户不透明。 与 .您可以使用 ,也可以创建自己的 。EncodingCursorStrategyCursorStrategyCursorEncoderBase64CursorEncoderNoOpEncoder
Spring Data 有一个内置的 。当 Spring Data 存在时,Boot Starter 会注册一个 with。CursorStrategyScrollPositionCursorStrategy<ScrollPosition>Base64Encoder
排序
在 GraphQL 请求中没有提供排序信息的标准方法。然而 分页取决于稳定的排序顺序。您可以使用默认订单,或者其他方式 公开输入类型并从 GraphQL 参数中提取排序详细信息。
内置了对 Spring Data 作为控制器的支持
method 参数。要使其正常工作,您需要有一个 bean。SortSortStrategy
| 1 | 创建具有一个或多个 s 的 type visitor 。ConnectionAdapter |
| 2 | 抵制类型的访客。 |
批量加载
给定 a 及其 ,我们可以为一本书创建一个 和 另一个
对于它的作者。这允许选择有作者或无作者的书籍,但这意味着书籍
和 authors 不会一起加载,这在查询多个
books 作为每本书的作者是单独加载的。这称为 N+1 选择
问题。BookAuthorDataFetcher
DataLoader
GraphQL Java 提供了一种批量加载相关实体的机制。
您可以在 GraphQL Java 文档中找到完整的详细信息。下面是一个
工作原理摘要:DataLoader
-
Register 的 ,可以加载实体,给定唯一键。
DataLoaderDataLoaderRegistry -
DataFetcher可以访问 并使用它们按 ID 加载实体。DataLoader -
A 通过返回 future 来延迟加载,以便可以批量完成。
DataLoader -
DataLoader维护加载实体的每个请求缓存,该缓存可以进一步 提高效率。
BatchLoaderRegistry
GraphQL Java 中的完整批处理加载机制需要实现以下之一
several 接口,然后将它们包装并注册为 S
名称位于 .BatchLoaderDataLoaderDataLoaderRegistry
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
您的配置,如上所示,或按顺序放入任何组件(如控制器)
注册批量加载函数。反过来,它被注入到确保每个请求的注册的位置。BatchLoaderRegistryBatchLoaderRegistryDefaultExecutionGraphQlServiceDataLoader
默认情况下,该名称基于目标实体的类名。
这允许方法使用泛型类型声明 DataLoader 参数,并且
无需指定名称。但是,如有必要,可以通过生成器自定义名称以及其他 .DataLoader@SchemaMappingBatchLoaderRegistryDataLoaderOptions
要全局配置 default,要用作任何
registration,你可以覆盖 Boot 的 bean 并使用构造函数
因为接受 .DataLoaderOptionsBatchLoaderRegistryDefaultBatchLoaderRegistrySupplier<DataLoaderOptions>
在许多情况下,在加载相关实体时,您可以使用 @BatchMapping 控制器方法,这是一种快捷方式
for 和 replace 需要使用 和 直接。BatchLoaderRegistryDataLoader
BatchLoaderRegistry还提供其他重要的好处。它支持访问
与 batch loading 函数和 from 方法相同,
以及确保对它们的上下文传播。这就是预期应用的原因
以使用它。可以直接执行自己的注册,但
此类注册将放弃上述好处。GraphQLContext@BatchMappingDataLoader
测试 Batch Loading
首先在 上执行注册 :BatchLoaderRegistryDataLoaderRegistry
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("...");
// ...