对于最新的稳定版本,请使用 Spring GraphQL 1.4.1spring-doc.cadn.net.cn

请求执行

ExecutionGraphQlService是调用 GraphQL Java 执行的主要 Spring 抽象 请求。基础传输(例如 HTTP)委托给ExecutionGraphQlService来处理请求。spring-doc.cadn.net.cn

主要实现DefaultExecutionGraphQlService,配置了GraphQlSource用于访问graphql.GraphQL实例调用。spring-doc.cadn.net.cn

GraphQLSource

GraphQlSource是一个合约,用于公开graphql.GraphQL实例也使用它 包括一个构建器 API,用于构建该实例。默认构建器可通过以下方式获得GraphQlSource.schemaResourceBuilder().spring-doc.cadn.net.cn

Boot Starter 创建此构建器的实例并进一步初始化它 要从可配置位置加载架构文件, 以公开要应用的属性GraphQlSource.Builder,以检测RuntimeWiringConfigurerbean、用于 GraphQL 指标检测 bean、 和DataFetcherExceptionResolverSubscriptionExceptionResolver用于异常解决的 bean。如需进一步自定义,您还可以 声明一个GraphQlSourceBuilderCustomizerbean,例如:spring-doc.cadn.net.cn

@Configuration(proxyBeanMethods = false)
class GraphQlConfig {

	@Bean
	public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
		return (builder) ->
				builder.configureGraphQl(graphQlBuilder ->
						graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
	}
}

架构资源

GraphQlSource.Builder可以配置一个或多个Resource实例 解析并合并在一起。这意味着模式文件几乎可以从任何 位置。spring-doc.cadn.net.cn

默认情况下,启动Starters会查找扩展名为 “.graphqls”或“.gqls”classpath:graphql/**,这通常是src/main/resources/graphql.您还可以使用文件系统位置或任何位置 由弹簧支持Resource层次结构,包括自定义实现 从远程位置、存储或内存加载架构文件。spring-doc.cadn.net.cn

classpath*:graphql/**/跨多个类路径查找架构文件 位置,例如跨多个模块。

架构创建

默认情况下,GraphQlSource.Builder使用 GraphQL JavaSchemaGenerator创建graphql.schema.GraphQLSchema.这适用于典型用途,但如果您需要使用 不同的生成器,例如对于联合,您可以注册一个schemaFactory回调:spring-doc.cadn.net.cn

GraphQlSource.Builder builder = ...

builder.schemaResources(..)
		.configureRuntimeWiring(..)
		.schemaFactory((typeDefinitionRegistry, runtimeWiring) -> {
			// create GraphQLSchema
		})

GraphQlSource 部分解释了如何使用 Spring Boot 进行配置。spring-doc.cadn.net.cn

有关 Apollo Federation 的示例,请参阅 federation-jvm-spring-examplespring-doc.cadn.net.cn

RuntimeWiringConfigurer

您可以使用RuntimeWiringConfigurer注册:spring-doc.cadn.net.cn

GraphQL Java,服务器应用程序仅使用 Jackson 进行数据映射的序列化。 客户端输入被解析为映射。服务器输出将根据字段选择集组合到地图中。 这意味着您不能依赖 Jackson 序列化/反序列化注释。 相反,您可以使用自定义标量类型

Boot Starter 检测类型为RuntimeWiringConfigurer和 将它们注册在GraphQlSource.Builder.这意味着在大多数情况下,您将拥有 配置中如下所示:spring-doc.cadn.net.cn

@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));
	}
}

如果您需要添加WiringFactory,例如进行注册时考虑到 模式定义,实现替代configure方法,该方法同时接受RuntimeWiring.Builder和输出List<WiringFactory>.这允许您添加任何 然后按顺序调用的工厂数。spring-doc.cadn.net.cn

TypeResolver

GraphQlSource.Builder寄存 器ClassNameTypeResolver作为默认值TypeResolver用于尚未进行此类注册的 GraphQL 接口和联合 通过RuntimeWiringConfigurer.目的 一个TypeResolver在 GraphQL 中,Java 是确定值的 GraphQL 对象类型 从DataFetcher用于 GraphQL 接口或联合字段。spring-doc.cadn.net.cn

ClassNameTypeResolver尝试将值的简单类名与 GraphQL 匹配 对象类型,如果不成功,它还会导航其超级类型,包括 基类和接口,寻找匹配项。ClassNameTypeResolver提供 配置名称提取功能的选项以及Class到 GraphQL 对象类型 应该有助于覆盖更多极端情况的名称映射:spring-doc.cadn.net.cn

GraphQlSource.Builder builder = ...
ClassNameTypeResolver classNameTypeResolver = new ClassNameTypeResolver();
classNameTypeResolver.setClassNameExtractor((klass) -> {
	// Implement Custom ClassName Extractor here
});
builder.defaultTypeResolver(classNameTypeResolver);

GraphQlSource 部分解释了如何使用 Spring Boot 进行配置。spring-doc.cadn.net.cn

指令

GraphQL 语言支持“描述替代运行时执行和 GraphQL 文档中的类型验证行为“。指令类似于 Java,但在 GraphQL 文档中的类型、字段、片段和作上声明。spring-doc.cadn.net.cn

GraphQL Java 提供了SchemaDirectiveWiring帮助应用程序检测的契约 和处理指令。有关更多详细信息,请参阅 GraphQL Java 文档。spring-doc.cadn.net.cn

在 Spring GraphQL 中,您可以注册一个SchemaDirectiveWiring通过RuntimeWiringConfigurer.启动Starters检测到 这样的 bean,所以你可能有类似的东西:spring-doc.cadn.net.cn

@Configuration
public class GraphQlConfig {

	 @Bean
	 public RuntimeWiringConfigurer runtimeWiringConfigurer() {
		  return builder -> builder.directiveWiring(new MySchemaDirectiveWiring());
	 }

}
有关指令支持的示例,请查看 Graphql Java 库的扩展验证

ExecutionStrategy

ExecutionStrategy在 GraphQL 中,Java 驱动获取请求的字段。 要创建ExecutionStrategy,您需要提供一个DataFetcherExceptionHandler. 默认情况下,Spring for GraphQL 会创建要使用的异常处理程序,如 Exceptions 中所述,并将其设置为GraphQL.Builder.然后,GraphQL Java 使用它来创建AsyncExecutionStrategy实例。spring-doc.cadn.net.cn

如果您需要创建自定义ExecutionStrategy,您可以检测DataFetcherExceptionResolvers 并以相同的方式创建一个异常处理程序,并使用 it 创建自定义ExecutionStrategy.例如,在 Spring Boot 应用程序中:spring-doc.cadn.net.cn

@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));
}

架构转换

您可以注册一个graphql.schema.GraphQLTypeVisitor通过builder.schemaResources(..).typeVisitorsToTransformSchema(..)如果要遍历 并在创建架构后对其进行转换,并对架构进行更改。记住 这比 Schema Traversal 更昂贵,因此通常 除非需要进行架构更改,否则更喜欢遍历而不是转换。spring-doc.cadn.net.cn

模式遍历

您可以注册一个graphql.schema.GraphQLTypeVisitor通过builder.schemaResources(..).typeVisitors(..)如果要在 它被创建,并可能对GraphQLCodeRegistry.请记住, 但是,此类访问者无法更改架构。如果需要对架构进行更改,请参阅架构转换spring-doc.cadn.net.cn

架构映射检查

如果查询、变更或订阅作没有DataFetcher,它不会 返回任何数据,并且不会做任何有用的事情。同样,返回架构类型的字段 通过既未通过DataFetcher注册,也不是默认的隐式PropertyDataFetcher,它会查找一个 匹配的 Java 对象属性,将始终是null.spring-doc.cadn.net.cn

GraphQL Java 不会执行检查以确保覆盖每个模式字段,并且可能会导致可能无法发现的差距,具体取决于测试覆盖率。在运行时您可能会收到“静默”null,如果字段不可为空,则为错误。作为较低级别 库,GraphQL Java 根本不够了解DataFetcherimplementations 和 它们的返回类型,因此无法将模式类型结构与 Java 对象进行比较 结构。spring-doc.cadn.net.cn

Spring for GraphQL 定义了SelfDescribingDataFetcher接口以允许DataFetcher以公开返回类型信息。整个SpringDataFetcher实现 实现此接口。这包括用于 Annotated Controller 的那些,以及用于 QuerydslQuery by Example Spring Data 存储库的那些。对于带注释的 controllers,则返回类型派生自@SchemaMapping方法。spring-doc.cadn.net.cn

启动时,Spring for GraphQL 可以检查模式字段,DataFetcher注册 以及从DataFetcher要检查的实现 如果所有架构字段都由显式注册的DataFetcher或 匹配的 Java 对象属性。检查还执行反向检查,寻找DataFetcher针对不存在的架构字段进行注册。spring-doc.cadn.net.cn

要启用架构映射的检查,请执行以下作:spring-doc.cadn.net.cn

GraphQlSource.Builder builder = ...

builder.schemaResources(..)
		.inspectSchemaMappings(report -> {
			logger.debug(report);
		})

下面是一个示例报告:spring-doc.cadn.net.cn

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 类型信息不足。如果带注释的控制器方法是 声明返回java.lang.Object,或者如果返回类型具有未指定的泛型 参数,例如List<?>,或者如果DataFetcher不实现SelfDescribingDataFetcher返回类型甚至不知道。在这种情况下, Java 对象类型结构仍然未知,模式类型在 生成的报告。对于每个跳过的类型,都会记录一条 DEBUG 消息以指示原因 它被跳过了。spring-doc.cadn.net.cn

模式联合类型总是被跳过,因为控制器方法无法在 Java 中声明这样的返回类型,并且 Java 类型结构未知。spring-doc.cadn.net.cn

模式接口类型仅支持直接声明的字段,这些字段是与SelfDescribingDataFetcher. 不检查具体实现上的其他字段。这可以改进在未来的版本中,还可以检查架构interface实现类型并尝试在声明的 Java 返回类型的子类型之间查找匹配项。spring-doc.cadn.net.cn

作缓存

GraphQL Java 必须在执行作之前对其进行解析验证。这可能会影响性能显着。为了避免需要重新解析和验证,应用程序可以配置一个PreparsedDocumentProvider缓存并重用文档实例。GraphQL Java 文档提供了更多详细信息通过PreparsedDocumentProvider.spring-doc.cadn.net.cn

在 Spring GraphQL 中,您可以注册一个PreparsedDocumentProvider通过GraphQlSource.Builder#configureGraphQl: .spring-doc.cadn.net.cn

// 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 进行配置。spring-doc.cadn.net.cn

螺纹模型

大多数 GraphQL 请求都受益于获取嵌套字段的并发执行。 这是 为什么当今大多数应用程序都依赖 GraphQL Java 的AsyncExecutionStrategy,这允许数据获取器返回CompletionStage并发执行而不是串行执行。spring-doc.cadn.net.cn

Java 21 和虚拟线程增加了有效使用更多线程的重要功能,但是仍然需要并发执行而不是串行执行,以便请求执行更快地完成。spring-doc.cadn.net.cn

Spring for GraphQL 支持:spring-doc.cadn.net.cn

Spring for GraphQL 在 Spring MVC 或 WebFlux 上运行作为传输。弹簧 MVC 使用异步请求执行,除非生成的CompletableFuture完成了 GraphQL Java 引擎返回后立即返回,如果 请求非常简单,不需要异步数据获取。spring-doc.cadn.net.cn

反应性的DataFetcher

默认值GraphQlSourcebuilder 启用了对DataFetcher返回MonoFlux它使这些调整为CompletableFuture哪里Flux值是聚合的 并转换为 List,除非该请求是 GraphQL 订阅请求, 在这种情况下,返回值仍为 Reactive StreamsPublisher用于流媒体 GraphQL 响应。spring-doc.cadn.net.cn

反应性DataFetcher可以依赖于对从 传输层,例如来自 WebFlux 请求处理,请参阅 WebFlux 上下文spring-doc.cadn.net.cn

上下文传播

Spring for GraphQL 支持通过 GraphQL Java 透明地传播上下文从 HTTP 传输,以及DataFetcher以及它调用的其他组件。这包括两者ThreadLocal上下文 来自 Spring MVC 请求处理线程和 ReactorContext来自 WebFlux 处理管道。spring-doc.cadn.net.cn

WebMvc 网站

一个DataFetcherGraphQL Java 调用的其他组件可能并不总是在 与 Spring MVC 处理程序相同的线程,例如,如果异步WebGraphQlInterceptorDataFetcher切换到 不同的线程。spring-doc.cadn.net.cn

Spring for GraphQL 支持传播ThreadLocalServlet 容器中的值 线程到线程 aDataFetcher以及 GraphQL Java 调用的其他组件 执行。为此,应用程序需要实现io.micrometer.context.ThreadLocalAccessor对于一个ThreadLocal感兴趣的值:spring-doc.cadn.net.cn

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机制。spring-doc.cadn.net.cn

WebFlux (网络通量)

一个反应性的DataFetcher可以依赖于对 Reactor 上下文的访问,即 源自 WebFlux 请求处理链。这包括 Reactor 上下文 由 WebGraphQlInterceptor 组件添加。spring-doc.cadn.net.cn

异常

在 GraphQL Java 中,DataFetcherExceptionHandler决定如何表示来自 响应的“错误”部分中的数据获取。应用程序可以注册 仅单个处理程序。spring-doc.cadn.net.cn

Spring for GraphQL 注册一个DataFetcherExceptionHandler提供默认 处理并启用DataFetcherExceptionResolver合同。应用程序可以 通过以下方式注册任意数量的解析器GraphQLSourcebuilder 和那些在 order 直到其中一个解决Exception设置为List<graphql.GraphQLError>. Spring Boot Starters检测这种类型的 bean。spring-doc.cadn.net.cn

DataFetcherExceptionResolverAdapter是一个方便的基类,具有受保护的方法resolveToSingleErrorresolveToMultipleErrors.spring-doc.cadn.net.cn

带注释的控制器编程模型支持使用带注释的异常处理程序方法处理具有灵活方法签名的方法,请参阅@GraphQlExceptionHandler了解详情。spring-doc.cadn.net.cn

一个GraphQLError可以分配给基于 GraphQL Java 的类别graphql.ErrorClassification,或 Spring GraphQLErrorType,它定义了以下内容:spring-doc.cadn.net.cn

如果异常仍未解决,则默认情况下将其分类为INTERNAL_ERROR使用包含类别名称和executionIdDataFetchingEnvironment. 该消息故意不透明,以避免泄露实现细节。应用程序可以使用DataFetcherExceptionResolver自定义错误详细信息。spring-doc.cadn.net.cn

未解决的异常将与executionId关联发送到客户端的错误。已解决的异常记录在 DEBUG 级别。spring-doc.cadn.net.cn

请求例外

GraphQL Java 引擎在解析请求时可能会遇到验证或其他错误这反过来又会阻止请求执行。在这种情况下,响应包含一个“data”键null以及一个或多个全局的请求级“错误”,即不是有一个字段路径。spring-doc.cadn.net.cn

DataFetcherExceptionResolver无法处理此类全局错误,因为它们被引发 在执行开始之前和任何执行之前DataFetcher被调用。应用程序可以使用 传输级拦截器,用于检查和转换ExecutionResult. 请参阅下面的示例WebGraphQlInterceptor.spring-doc.cadn.net.cn

订阅例外

Publisher对于订阅请求,可能会以错误信号完成,在这种情况下 底层传输(例如 WebSocket)发送带有列表的最终“错误”类型消息 的 GraphQL 错误。spring-doc.cadn.net.cn

DataFetcherExceptionResolver无法解决订阅中的错误Publisher, 自数据DataFetcher仅创建Publisher最初。之后, transport 订阅Publisher然后可能会以错误完成。spring-doc.cadn.net.cn

应用程序可以注册SubscriptionExceptionResolver为了解决 订阅的例外情况Publisher为了将这些错误解决为 GraphQL 错误 发送给客户端。spring-doc.cadn.net.cn

分页

GraphQL 游标连接规范定义了一种导航大型结果集的方法,方法是在以下时间返回项目子集 每个项目都与一个游标配对,客户端可以使用该游标在 或 在引用的项之后。spring-doc.cadn.net.cn

该规范将该模式称为“连接”。名称结尾的架构类型 on Connection 是表示分页结果集的连接类型。都~Connection类型包含一个“edges”字段,其中~Edgetype 将实际项与游标配对,如 以及带有布尔标志的“pageInfo”字段,以指示是否有更多项目向前 和向后。spring-doc.cadn.net.cn

连接类型

Connection必须为每个需要分页的类型创建类型定义,将 样板和噪声。Spring for GraphQL 提供ConnectionTypeDefinitionConfigurer在启动时添加这些类型(如果尚未添加) 存在于解析的架构文件中。这意味着在架构中,您只需要以下内容:spring-doc.cadn.net.cn

Query {
	books(first:Int, after:String, last:Int, before:String): BookConnection
}

type Book {
	id: ID!
	title: String!
}

请注意规范定义的正向分页参数firstafter客户端可以使用 请求给定游标之后的前 N 个项目,而lastbefore是落后的 分页参数来请求给定游标之前的最后 N 个项目。spring-doc.cadn.net.cn

接下来,配置ConnectionTypeDefinitionConfigurer如下:spring-doc.cadn.net.cn

GraphQlSource.schemaResourceBuilder()
		.schemaResources(..)
		.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer)

以下类型定义将透明地添加到架构中:spring-doc.cadn.net.cn

type BookConnection {
	edges: [BookEdge]!
	pageInfo: PageInfo!
}

type BookEdge {
	node: Book!
	cursor: String!
}

type PageInfo {
	hasPreviousPage: Boolean!
	hasNextPage: Boolean!
	startCursor: String
	endCursor: String
}

启动Starters注册ConnectionTypeDefinitionConfigurer默认情况下。spring-doc.cadn.net.cn

ConnectionAdapter

在架构中提供连接类型后,您还需要 等效的 Java 类型。GraphQL Java 提供了这些,包括通用ConnectionEdge,以及PageInfo.spring-doc.cadn.net.cn

一种选择是填充Connection并从您的控制器方法返回它,或者DataFetcher.但是,这需要样板代码来创建Connection, 创建游标,将每个项目包装为Edge,并创建PageInfo. 此外,您可能已经有一个底层的分页机制,例如在使用 Spring Data 存储库。spring-doc.cadn.net.cn

Spring for GraphQL 定义了ConnectionAdapter适应项目容器的合同 自Connection.适配器通过DataFetcher反过来是装饰器 通过ConnectionFieldTypeVisitor.您可以按如下方式配置它:spring-doc.cadn.net.cn

ConnectionAdapter adapter = ... ;
GraphQLTypeVisitor visitor = ConnectionFieldTypeVisitor.create(List.of(adapter)) (1)

GraphQlSource.schemaResourceBuilder()
		.schemaResources(..)
		.typeDefinitionConfigurer(..)
		.typeVisitors(List.of(visitor)) (2)
1 创建具有一个或多个访客的类型ConnectionAdapters.
2 拒绝类型访问者。

内置的 ConnectionAdapters 表示 Spring Data 的WindowSlice.您还可以创建自己的自定义适配器。ConnectionAdapter实现依赖于CursorStrategy自 为退回的项目创建游标。同样的策略也用于支持Subrangecontroller 方法参数,其中包含 分页输入。spring-doc.cadn.net.cn

CursorStrategy

CursorStrategy是一个用于编码和解码 String 游标的合约,该游标引用 项在大型结果集中的位置。游标可以基于索引或 在键集上。spring-doc.cadn.net.cn

一个ConnectionAdapter使用它对返回项的游标进行编码。带注释的控制器方法、Querydsl 存储库和按示例查询存储库使用它来解码分页请求中的游标,并创建一个Subrange.spring-doc.cadn.net.cn

CursorEncoder是一个相关的合约,它进一步编码和解码 String 游标 使它们对客户不透明。EncodingCursorStrategy结合CursorStrategy使用CursorEncoder.您可以使用Base64CursorEncoder,NoOpEncoder或创建您自己的。spring-doc.cadn.net.cn

有一个内置的 CursorStrategy对于 Spring DataScrollPosition.Boot Starter 注册一个CursorStrategy<ScrollPosition>Base64Encoder当 Spring Data 存在时。spring-doc.cadn.net.cn

排序

在 GraphQL 请求中没有提供排序信息的标准方法。然而 分页取决于稳定的排序顺序。您可以使用默认订单,或者其他方式 公开输入类型并从 GraphQL 参数中提取排序详细信息。spring-doc.cadn.net.cn

内置支持 Spring Data 的Sort作为控制器 method 参数。为此,您需要有一个SortStrategy豆。spring-doc.cadn.net.cn

批量装载

给定一个Book及其Author,我们可以创建一个DataFetcher为一本书和另一本书 对于它的作者。这允许选择有或没有作者的书籍,但这意味着书籍 并且作者不会一起加载,这在查询多个 books 作为每本书的作者被单独加载。这称为 N+1 选择 问题。spring-doc.cadn.net.cn

DataLoader

GraphQL Java 提供了一个DataLoader相关实体批量加载的机制。 您可以在 GraphQL Java 文档中找到完整的详细信息。下面是一个 工作原理摘要:spring-doc.cadn.net.cn

  1. 注册DataLoaderDataLoaderRegistry可以加载给定唯一键的实体。spring-doc.cadn.net.cn

  2. DataFetcher的可以访问DataLoader的,并使用它们按 id 加载实体。spring-doc.cadn.net.cn

  3. 一个DataLoader通过返回 future 来延迟加载,以便可以批量完成。spring-doc.cadn.net.cn

  4. DataLoader的维护加载实体的每个请求缓存,这些实体可以进一步 提高效率。spring-doc.cadn.net.cn

BatchLoaderRegistry

GraphQL Java 中的完整批处理加载机制需要实现 几个BatchLoader接口,然后将它们包装并注册为DataLoaders 在DataLoaderRegistry.spring-doc.cadn.net.cn

Spring GraphQL 中的 API 略有不同。对于注册,只有一个, 中央BatchLoaderRegistry公开工厂方法和构建器以创建和 注册任意数量的批量加载函数:spring-doc.cadn.net.cn

@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 声明BatchLoaderRegistry您可以注入的 bean 您的配置,如上所示,或按顺序插入任何组件(例如控制器) 注册批量加载函数。反过来,BatchLoaderRegistry被注入DefaultExecutionGraphQlService确保DataLoader每个请求的注册数。spring-doc.cadn.net.cn

默认情况下,DataLoadername 基于目标实体的类名。 这允许@SchemaMapping方法来声明具有泛型类型的 DataLoader 参数,以及 无需指定名称。但是,可以通过BatchLoaderRegistry构建器,如有必要,以及其他DataLoaderOptions.spring-doc.cadn.net.cn

配置默认值DataLoaderOptions全局,用作任何 注册,您可以覆盖 Boot 的BatchLoaderRegistrybean 并使用 为DefaultBatchLoaderRegistry接受Supplier<DataLoaderOptions>.spring-doc.cadn.net.cn

在许多情况下,在加载相关实体时,可以使用@BatchMapping控制器方法,这是一种快捷方式 为和取代需要使用BatchLoaderRegistryDataLoader径直。spring-doc.cadn.net.cn

BatchLoaderRegistry还提供其他重要的好处。它支持访问 一样GraphQLContext从 batch loading 函数和 from@BatchMapping方法 并确保上下文传播到它们。这就是需要应用的原因 使用它。可以自己执行DataLoader直接注册,但 此类注册将放弃上述好处。spring-doc.cadn.net.cn

测试批量加载

首先拥有BatchLoaderRegistryDataLoaderRegistry:spring-doc.cadn.net.cn

BatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();
// perform registrations...

DataLoaderRegistry dataLoaderRegistry = DataLoaderRegistry.newRegistry().build();
batchLoaderRegistry.registerDataLoaders(dataLoaderRegistry, graphQLContext);

现在您可以访问和测试单个DataLoader如下:spring-doc.cadn.net.cn

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("...");
// ...