Spring for GraphQL 提供了一个基于注解的编程模型,其中组件使用注解来声明具有灵活方法签名的处理程序方法,以 获取特定 GraphQL 字段的数据。例如:@ControllerSpring中文文档

@Controller
public class GreetingController {

		@QueryMapping (1)
		public String hello() { (2)
			return "Hello, world!";
		}

}
1 将此方法绑定到查询,即 Query 类型下的字段。
2 如果未在批注中声明,则从方法名称确定查询。

Spring for GraphQL 用于将上述处理程序方法注册为名为“hello”的查询。RuntimeWiring.Buildergraphql.schema.DataFetcherSpring中文文档

1 将此方法绑定到查询,即 Query 类型下的字段。
2 如果未在批注中声明,则从方法名称确定查询。

声明

您可以将 Bean 定义为标准的 Spring Bean 定义。构造型允许自动检测,与 Spring general 一致 支持类路径上的检测和类,以及 自动注册它们的 Bean 定义。它还充当注释的刻板印象 类,指示其在 GraphQL 应用程序中作为数据获取组件的角色。@Controller@Controller@Controller@ComponentSpring中文文档

AnnotatedControllerConfigurer检测 Bean 并注册其 注释处理程序方法如 S 通过 。这是一个 可以将其的实现添加到 中。 Boot Starter 自动声明为 Bean 并将所有 bean 添加到 和 支持带注释的 s,请参阅 GraphQL RuntimeWiring 部分 在启动初学者文档中。@ControllerDataFetcherRuntimeWiring.BuilderRuntimeWiringConfigurerGraphQlSource.BuilderAnnotatedControllerConfigurerRuntimeWiringConfigurerGraphQlSource.BuilderDataFetcherSpring中文文档

@SchemaMapping

注释将处理程序方法映射到 GraphQL 架构中的字段 并声明它是该字段的。注解可以指定 父类型名称和字段名称:@SchemaMappingDataFetcherSpring中文文档

@Controller
public class BookController {

	@SchemaMapping(typeName="Book", field="author")
	public Author getAuthor(Book book) {
		// ...
	}
}

注解还可以省略这些属性,在这种情况下, 字段名称默认为方法名称,而类型名称默认为简单类 注入到方法中的源/父对象的名称。例如,以下 默认键入“Book”和字段“author”:@SchemaMappingSpring中文文档

@Controller
public class BookController {

	@SchemaMapping
	public Author author(Book book) {
		// ...
	}
}

可以在类级别声明注释以指定默认值 键入类中所有处理程序方法的 name。@SchemaMappingSpring中文文档

@Controller
@SchemaMapping(typeName="Book")
public class BookController {

	// @SchemaMapping methods for fields of the "Book" type

}

@QueryMapping、 和 是元注释 它们本身分别用 和 typeName 预设为 、 或 进行注释。实际上,这些是快捷方式注释 分别用于 Query、Mutation 和 Subscription 类型下的字段。例如:@MutationMapping@SubscriptionMapping@SchemaMappingQueryMutationSubscriptionSpring中文文档

@Controller
public class BookController {

	@QueryMapping
	public Book bookById(@Argument Long id) {
		// ...
	}

	@MutationMapping
	public Book addBook(@Argument BookInput bookInput) {
		// ...
	}

	@SubscriptionMapping
	public Flux<Book> newPublications() {
		// ...
	}
}

@SchemaMapping处理程序方法具有灵活的签名,可以从一系列 方法参数和返回值。.Spring中文文档

方法参数

架构映射处理程序方法可以具有以下任何方法参数:Spring中文文档

Method 参数 描述

@ArgumentSpring中文文档

用于访问绑定到更高级别的类型化 Object 的命名字段参数。Spring中文文档

请参见@ArgumentSpring中文文档

@Argument Map<String, Object>Spring中文文档

用于访问原始参数值。Spring中文文档

请参见@ArgumentSpring中文文档

ArgumentValueSpring中文文档

用于访问绑定到更高级别的类型化 Object 的命名字段参数 带有一个标志,指示输入参数是否被省略,vs 设置为 。nullSpring中文文档

请参阅 ArgumentValueSpring中文文档

@ArgumentsSpring中文文档

用于访问绑定到更高级别的类型化 Object 的所有字段参数。Spring中文文档

请参见@ArgumentsSpring中文文档

@Arguments Map<String, Object>Spring中文文档

用于访问参数的原始映射。Spring中文文档

@ProjectedPayload接口Spring中文文档

用于通过项目接口访问字段参数。Spring中文文档

请参阅@ProjectedPayload界面Spring中文文档

“来源”Spring中文文档

用于访问字段的源(即父/容器)实例。Spring中文文档

请参阅Spring中文文档

SubrangeScrollSubrangeSpring中文文档

用于访问分页参数。Spring中文文档

请参见分页滚动子范围Spring中文文档

SortSpring中文文档

用于访问排序详细信息。Spring中文文档

请参阅分页排序Spring中文文档

DataLoaderSpring中文文档

要访问 .DataLoaderDataLoaderRegistrySpring中文文档

请参阅 DataLoaderSpring中文文档

@ContextValueSpring中文文档

用于从 main 中的属性访问 。GraphQLContextDataFetchingEnvironmentSpring中文文档

@LocalContextValueSpring中文文档

用于从 中的本地访问属性。GraphQLContextDataFetchingEnvironmentSpring中文文档

GraphQLContextSpring中文文档

要从 .DataFetchingEnvironmentSpring中文文档

java.security.PrincipalSpring中文文档

从 Spring Security 上下文中获取(如果可用)。Spring中文文档

@AuthenticationPrincipalSpring中文文档

用于从 Spring Security 上下文访问。Authentication#getPrincipal()Spring中文文档

DataFetchingFieldSelectionSetSpring中文文档

要通过 .DataFetchingEnvironmentSpring中文文档

Locale,Optional<Locale>Spring中文文档

要从 .LocaleDataFetchingEnvironmentSpring中文文档

DataFetchingEnvironmentSpring中文文档

用于直接访问底层 .DataFetchingEnvironmentSpring中文文档

返回值

架构映射处理程序方法可以返回:Spring中文文档

在 Java 21+ 上,当配置了 、 控制器 具有阻塞方法签名的方法以异步方式调用。默认情况下,控制器 如果 method 不返回异步类型(如 、 、 ),并且也不是 Kotlin 挂起函数,则该方法被视为阻塞。您可以配置一个 阻止控制器方法打开以帮助 确定哪些方法被视为阻塞。AnnotatedControllerConfigurerExecutorFluxMonoCompletableFuturePredicateAnnotatedControllerConfigurerSpring中文文档

设置 Spring for GraphQL 的 Spring Boot 启动器会自动配置 for 虚拟线程。AnnotatedControllerConfigurerExecutorspring.threads.virtual.enabled

接口架构映射

当控制器方法映射到架构接口字段时,默认情况下,映射为 替换为多个映射,每个映射对应实现接口的每个架构对象类型。 这允许对所有子类型使用一种控制器方法。Spring中文文档

例如,给定:Spring中文文档

type Query {
	activities: [Activity!]!
}

interface Activity {
	id: ID!
	coordinator: User!
}

type FooActivity implements Activity {
	id: ID!
	coordinator: User!
}

type BarActivity implements Activity {
	id: ID!
	coordinator: User!
}

type User {
	name: String!
}

你可以像这样编写一个控制器:Spring中文文档

@Controller
public class BookController {

	@QueryMapping
	public List<Activity> activities() {
		// ...
	}

	@SchemaMapping
	public User coordinator(Activity activity) {
		// Called for any Activity subtype
	}

}

如有必要,您可以接管各个子类型的映射:Spring中文文档

@Controller
public class BookController {

	@QueryMapping
	public List<Activity> activities() {
		// ...
	}

	@SchemaMapping
	public User coordinator(Activity activity) {
		// Called for any Activity subtype except FooActivity
	}

	@SchemaMapping
	public User coordinator(FooActivity activity) {
		// ...
	}

}

@Argument

在 GraphQL Java 中,提供对特定于字段的映射的访问 参数值。这些值可以是简单的标量值(例如 String、Long)、a values 表示更复杂的输入,或 a of 值。DataFetchingEnvironmentMapListSpring中文文档

使用注释将参数绑定到目标对象,并且 注入到处理程序方法中。绑定是通过将参数值映射到 预期方法参数类型的主数据构造函数,或使用默认值 构造函数来创建对象,然后将参数值映射到其属性。这是 递归重复,使用所有嵌套的参数值并创建嵌套的目标对象 因此。例如:@ArgumentSpring中文文档

@Controller
public class BookController {

	@QueryMapping
	public Book bookById(@Argument Long id) {
		// ...
	}

	@MutationMapping
	public Book addBook(@Argument BookInput bookInput) {
		// ...
	}
}
如果目标对象没有 setter,并且您无法更改它,则可以使用 属性,以允许回退到通过直接绑定 字段访问。AnnotatedControllerConfigurer

默认情况下,如果方法参数名称可用(需要编译器 标志与Java 8+或来自编译器的调试信息),它用于查找参数。 如果需要,您可以通过注释自定义名称,例如 .-parameters@Argument("bookInput")Spring中文文档

注释没有“必需”标志,也没有 指定默认值。这两者都可以在 GraphQL 模式级别指定,并且 由 GraphQL Java 强制执行。@Argument

如果绑定失败,则会引发绑定问题,并将绑定问题累积为字段 错误,其中每个错误的是发生问题的参数路径。BindExceptionfieldSpring中文文档

您可以与参数一起使用,以获取 参数。例如:@ArgumentMap<String, Object>Spring中文文档

@Controller
public class BookController {

	@MutationMapping
	public Book addBook(@Argument Map<String, Object> bookInput) {
		// ...
	}
}
在 1.2 之前,如果 注释没有指定名称。在 1.2 之后,with 始终返回原始参数值,与名称匹配 在批注中指定,或指定到参数名称。访问完整参数 地图,请改用@Arguments@Argument Map<String, Object>@ArgumentMap<String, Object>

ArgumentValue

默认情况下,GraphQL 中的输入参数是可为 null 且可选的,这意味着参数 可以设置为文本,也可以根本不提供。这种区别对以下方面很有用 具有突变的部分更新,其中基础数据也可能被设置为或根本不发生相应更改。使用@Argument时,无法进行这样的区分,因为在这两种情况下,您都会得到或空。nullnullnullOptionalSpring中文文档

如果你不想知道是否根本没有提供值,你可以声明一个方法参数,它是结果值的简单容器, 以及一个标志,用于指示是否完全省略了输入参数。你 可以使用 this 代替 ,在这种情况下,参数名称由 方法参数名称,或与一起指定参数名称。ArgumentValue@Argument@ArgumentSpring中文文档

@Controller
public class BookController {

	@MutationMapping
	public void addBook(ArgumentValue<BookInput> bookInput) {
		if (!bookInput.isOmitted()) {
			BookInput value = bookInput.value();
			// ...
		}
	}
}

ArgumentValue也支持作为方法参数的对象结构中的字段,通过构造函数参数或通过 setter 初始化,包括 作为嵌套在顶级对象下方的任何级别的对象的字段。@ArgumentSpring中文文档

@Arguments

如果要将完整的参数映射绑定到单个参数上,请使用注释 target Object,与绑定特定的命名参数相反。@Arguments@ArgumentSpring中文文档

例如,使用参数“bookInput”的值 初始化 ,而使用完整的参数映射,并且 case,顶级参数绑定到属性。@Argument BookInput bookInputBookInput@ArgumentsBookInputSpring中文文档

你可以与参数一起使用,以获得 所有参数值。@ArgumentsMap<String, Object>Spring中文文档

@ProjectedPayload接口

作为使用带有@Argument的完整对象的替代方法, 您还可以使用投影接口通过 定义明确、最小的界面。当 Spring Data 位于类路径上时,参数投影由 Spring Data 的接口投影提供。Spring中文文档

要利用这一点,请创建一个带有注释的接口并声明 它作为控制器方法参数。如果参数注释为 , 它适用于映射中的单个参数。当声明为 without 时,投影适用于 完整的参数映射。@ProjectedPayload@ArgumentDataFetchingEnvironment.getArguments()@ArgumentSpring中文文档

@Controller
public class BookController {

	@QueryMapping
	public Book bookById(BookIdProjection bookId) {
		// ...
	}

	@MutationMapping
	public Book addBook(@Argument BookInputProjection bookInput) {
		// ...
	}
}

@ProjectedPayload
interface BookIdProjection {

	Long getId();
}

@ProjectedPayload
interface BookInputProjection {

	String getName();

	@Value("#{target.author + ' ' + target.name}")
	String getAuthorAndName();
}

在 GraphQL Java 中,提供对源代码的访问(即 parent/container) 实例。要访问它,只需声明一个方法参数 预期的目标类型。DataFetchingEnvironmentSpring中文文档

@Controller
public class BookController {

	@SchemaMapping
	public Author author(Book book) {
		// ...
	}
}

source 方法参数还有助于确定映射的类型名称。 如果 Java 类的简单名称与 GraphQL 类型匹配,则无需 在批注中显式指定类型名称。@SchemaMappingSpring中文文档

@BatchMapping处理程序方法可以批量加载查询的所有作者, 给定源/父书籍对象的列表。Spring中文文档

Subrange

当 Spring 配置中有 CursorStrategy bean 时, 控制器方法支持参数,其中 is 相对位置 从光标转换而来。对于 Spring Data,公开 . 例如:Subrange<P><P>ScrollSubrangeScrollPositionSpring中文文档

@Controller
public class BookController {

	@QueryMapping
	public Window<Book> books(ScrollSubrange subrange) {
		ScrollPosition position = subrange.position().orElse(ScrollPosition.offset());
		int count = subrange.count().orElse(20);
		// ...
	}

}

有关分页和内置机制的概述,请参阅分页Spring中文文档

Sort

当 Spring 配置中有 SortStrategy bean 时,控制器 方法支持作为方法参数。例如:SortSpring中文文档

@Controller
public class BookController {

	@QueryMapping
	public Window<Book> books(Optional<Sort> optionalSort) {
		Sort sort = optionalSort.orElse(Sort.by(..));
	}

}

DataLoader

当您为实体注册批量加载函数时,如批量加载中所述,您可以通过声明 method 参数,并使用它来加载实体:DataLoaderDataLoaderSpring中文文档

@Controller
public class BookController {

	public BookController(BatchLoaderRegistry registry) {
		registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
			// return Map<Long, Author>
		});
	}

	@SchemaMapping
	public CompletableFuture<Author> author(Book book, DataLoader<Long, Author> loader) {
		return loader.load(book.getAuthorId());
	}

}

默认情况下,使用值类型的完整类名(例如 class name for ) 作为注册的密钥,因此只需声明 具有泛型类型的 method 参数提供了足够的信息 将其定位在 .作为回退,method 参数 解析器还会尝试将方法参数名称作为键,但通常不应该这样做 是必要的。BatchLoaderRegistryAuthorDataLoaderDataLoaderRegistryDataLoaderSpring中文文档

请注意,对于许多加载相关实体的情况,其中 委托给 ,您可以使用 @BatchMapping 方法减少样板,如下一节所述。@SchemaMappingDataLoaderSpring中文文档

验证

找到 Bean 时,启用对带注释的控制器方法的 Bean 验证的支持。通常,Bean 的类型为 。javax.validation.ValidatorAnnotatedControllerConfigurerLocalValidatorFactoryBeanSpring中文文档

Bean 验证允许您声明对类型的约束:Spring中文文档

public class BookInput {

	@NotNull
	private String title;

	@NotNull
	@Size(max=13)
	private String isbn;
}

然后,您可以对控制器方法参数进行注释,以便在之前对其进行验证 方法调用:@ValidSpring中文文档

@Controller
public class BookController {

	@MutationMapping
	public Book addBook(@Argument @Valid BookInput bookInput) {
		// ...
	}
}

如果在验证过程中发生错误,则会引发 a。 您可以使用“异常”链来决定如何将其呈现给客户端 通过将其转换为错误以包含在 GraphQL 响应中。ConstraintViolationExceptionSpring中文文档

除了 ,您还可以使用 Spring 的允许 指定验证组。@Valid@Validated

Bean 验证对 @Argument@Arguments@ProjectedPayload 方法参数很有用,但更普遍地适用于任何方法参数。Spring中文文档

验证和 Kotlin 协程

Hibernate Validator 与 Kotlin 协程方法不兼容,并且在以下情况下失败 反省他们的方法参数。请参阅 spring-projects/spring-graphql#344 (注释) 有关相关问题的链接和建议的解决方法。Spring中文文档

Method 参数 描述

@ArgumentSpring中文文档

用于访问绑定到更高级别的类型化 Object 的命名字段参数。Spring中文文档

请参见@ArgumentSpring中文文档

@Argument Map<String, Object>Spring中文文档

用于访问原始参数值。Spring中文文档

请参见@ArgumentSpring中文文档

ArgumentValueSpring中文文档

用于访问绑定到更高级别的类型化 Object 的命名字段参数 带有一个标志,指示输入参数是否被省略,vs 设置为 。nullSpring中文文档

请参阅 ArgumentValueSpring中文文档

@ArgumentsSpring中文文档

用于访问绑定到更高级别的类型化 Object 的所有字段参数。Spring中文文档

请参见@ArgumentsSpring中文文档

@Arguments Map<String, Object>Spring中文文档

用于访问参数的原始映射。Spring中文文档

@ProjectedPayload接口Spring中文文档

用于通过项目接口访问字段参数。Spring中文文档

请参阅@ProjectedPayload界面Spring中文文档

“来源”Spring中文文档

用于访问字段的源(即父/容器)实例。Spring中文文档

请参阅Spring中文文档

SubrangeScrollSubrangeSpring中文文档

用于访问分页参数。Spring中文文档

请参见分页滚动子范围Spring中文文档

SortSpring中文文档

用于访问排序详细信息。Spring中文文档

请参阅分页排序Spring中文文档

DataLoaderSpring中文文档

要访问 .DataLoaderDataLoaderRegistrySpring中文文档

请参阅 DataLoaderSpring中文文档

@ContextValueSpring中文文档

用于从 main 中的属性访问 。GraphQLContextDataFetchingEnvironmentSpring中文文档

@LocalContextValueSpring中文文档

用于从 中的本地访问属性。GraphQLContextDataFetchingEnvironmentSpring中文文档

GraphQLContextSpring中文文档

要从 .DataFetchingEnvironmentSpring中文文档

java.security.PrincipalSpring中文文档

从 Spring Security 上下文中获取(如果可用)。Spring中文文档

@AuthenticationPrincipalSpring中文文档

用于从 Spring Security 上下文访问。Authentication#getPrincipal()Spring中文文档

DataFetchingFieldSelectionSetSpring中文文档

要通过 .DataFetchingEnvironmentSpring中文文档

Locale,Optional<Locale>Spring中文文档

要从 .LocaleDataFetchingEnvironmentSpring中文文档

DataFetchingEnvironmentSpring中文文档

用于直接访问底层 .DataFetchingEnvironmentSpring中文文档

设置 Spring for GraphQL 的 Spring Boot 启动器会自动配置 for 虚拟线程。AnnotatedControllerConfigurerExecutorspring.threads.virtual.enabled
如果目标对象没有 setter,并且您无法更改它,则可以使用 属性,以允许回退到通过直接绑定 字段访问。AnnotatedControllerConfigurer
注释没有“必需”标志,也没有 指定默认值。这两者都可以在 GraphQL 模式级别指定,并且 由 GraphQL Java 强制执行。@Argument
在 1.2 之前,如果 注释没有指定名称。在 1.2 之后,with 始终返回原始参数值,与名称匹配 在批注中指定,或指定到参数名称。访问完整参数 地图,请改用@Arguments@Argument Map<String, Object>@ArgumentMap<String, Object>

@BatchMapping处理程序方法可以批量加载查询的所有作者, 给定源/父书籍对象的列表。Spring中文文档

除了 ,您还可以使用 Spring 的允许 指定验证组。@Valid@Validated
验证和 Kotlin 协程

Hibernate Validator 与 Kotlin 协程方法不兼容,并且在以下情况下失败 反省他们的方法参数。请参阅 spring-projects/spring-graphql#344 (注释) 有关相关问题的链接和建议的解决方法。Spring中文文档

@BatchMapping

批量加载通过使用 an 延迟单个实体实例的加载来解决 N+1 选择问题,因此它们 可以一起加载。例如:org.dataloader.DataLoaderSpring中文文档

@Controller
public class BookController {

	public BookController(BatchLoaderRegistry registry) {
		registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
			// return Map<Long, Author>
		});
	}

	@SchemaMapping
	public CompletableFuture<Author> author(Book book, DataLoader<Long, Author> loader) {
		return loader.load(book.getAuthorId());
	}

}

对于加载关联实体的直接情况(如上所示),该方法只执行委托给 .这是 可以通过一种方法避免的样板。例如:@SchemaMappingDataLoader@BatchMappingSpring中文文档

@Controller
public class BookController {

	@BatchMapping
	public Mono<Map<Book, Author>> author(List<Book> books) {
		// ...
	}
}

上面变成了一个批量加载函数,其中键是实例,加载值是它们的作者。此外,a 还透明地绑定到类型的字段,其中 只需委托给 for 作者,给定其源/父实例。BatchLoaderRegistryBookDataFetcherauthorBookDataLoaderBookSpring中文文档

要用作唯一键,必须实现 和 。BookhashcodeequalsSpring中文文档

默认情况下,字段名称默认为方法名称,而类型名称默认为 输入元素类型的简单类名。两者都可以通过以下方式进行定制 Annotation 属性。类型名称也可以从类级别继承。List@SchemaMappingSpring中文文档

方法参数

批处理映射方法支持以下参数:Spring中文文档

Method 参数 描述

List<K>Spring中文文档

源/父对象。Spring中文文档

java.security.PrincipalSpring中文文档

从 Spring Security 上下文(如果可用)获取。Spring中文文档

@ContextValueSpring中文文档

要访问 的值 , 这与 .GraphQLContextBatchLoaderEnvironmentDataFetchingEnvironmentSpring中文文档

GraphQLContextSpring中文文档

要从 , 这与 .BatchLoaderEnvironmentDataFetchingEnvironmentSpring中文文档

BatchLoaderEnvironmentSpring中文文档

在 GraphQL Java 中可用的环境到 .org.dataloader.BatchLoaderWithContextSpring中文文档

返回值

批处理映射方法可以返回:Spring中文文档

返回类型 描述

Mono<Map<K,V>>Spring中文文档

将父对象作为键,将批量加载的对象作为值的映射。Spring中文文档

Flux<V>Spring中文文档

批处理加载对象的序列,其顺序必须与源/父对象的顺序相同 传递到方法中的对象。Spring中文文档

Map<K,V>,Collection<V>Spring中文文档

命令式变体,例如无需进行远程调用。Spring中文文档

Callable<Map<K,V>>,Callable<Collection<V>>Spring中文文档

要异步调用的命令式变体。为此,必须配置 .AnnotatedControllerConfigurerExecutorSpring中文文档

Kotlin 协程与 、 Kotlin 的协程Map<K,V>Flow<K,V>Spring中文文档

适用于 和 .Mono<Map<K,V>Flux<V>Spring中文文档

在 Java 21+ 上,当配置了 、 控制器 具有阻塞方法签名的方法以异步方式调用。默认情况下,控制器 如果 method 不返回异步类型(如 、 、 ),并且也不是 Kotlin 挂起函数,则该方法被视为阻塞。您可以配置一个 阻止控制器方法打开以帮助 确定哪些方法被视为阻塞。AnnotatedControllerConfigurerExecutorFluxMonoCompletableFuturePredicateAnnotatedControllerConfigurerSpring中文文档

设置 Spring for GraphQL 的 Spring Boot 启动器会自动配置 for 虚拟线程。AnnotatedControllerConfigurerExecutorspring.threads.virtual.enabled

接口批处理映射

接口架构映射一样, 当批量映射方法映射到架构接口字段时,该映射将替换为 多个映射,每个映射对应实现接口的每个架构对象类型。Spring中文文档

这意味着,鉴于以下情况:Spring中文文档

type Query {
	activities: [Activity!]!
}

interface Activity {
	id: ID!
	coordinator: User!
}

type FooActivity implements Activity {
	id: ID!
	coordinator: User!
}

type BarActivity implements Activity {
	id: ID!
	coordinator: User!
}

type User {
	name: String!
}

你可以像这样编写一个控制器:Spring中文文档

@Controller
public class BookController {

	@QueryMapping
	public List<Activity> activities() {
		// ...
	}

	@BatchMapping
	Map<Activity, User> coordinator(List<Activity> activities) {
		// Called for all Activity subtypes
	}
}

如有必要,您可以接管各个子类型的映射:Spring中文文档

@Controller
public class BookController {

	@QueryMapping
	public List<Activity> activities() {
		// ...
	}

	@BatchMapping
	Map<Activity, User> coordinator(List<Activity> activities) {
		// Called for all Activity subtypes
	}

	@BatchMapping(field = "coordinator")
	Map<Activity, User> fooCoordinator(List<FooActivity> activities) {
		// ...
	}
}

要用作唯一键,必须实现 和 。BookhashcodeequalsSpring中文文档

Method 参数 描述

List<K>Spring中文文档

源/父对象。Spring中文文档

java.security.PrincipalSpring中文文档

从 Spring Security 上下文(如果可用)获取。Spring中文文档

@ContextValueSpring中文文档

要访问 的值 , 这与 .GraphQLContextBatchLoaderEnvironmentDataFetchingEnvironmentSpring中文文档

GraphQLContextSpring中文文档

要从 , 这与 .BatchLoaderEnvironmentDataFetchingEnvironmentSpring中文文档

BatchLoaderEnvironmentSpring中文文档

在 GraphQL Java 中可用的环境到 .org.dataloader.BatchLoaderWithContextSpring中文文档

返回类型 描述

Mono<Map<K,V>>Spring中文文档

将父对象作为键,将批量加载的对象作为值的映射。Spring中文文档

Flux<V>Spring中文文档

批处理加载对象的序列,其顺序必须与源/父对象的顺序相同 传递到方法中的对象。Spring中文文档

Map<K,V>,Collection<V>Spring中文文档

命令式变体,例如无需进行远程调用。Spring中文文档

Callable<Map<K,V>>,Callable<Collection<V>>Spring中文文档

要异步调用的命令式变体。为此,必须配置 .AnnotatedControllerConfigurerExecutorSpring中文文档

Kotlin 协程与 、 Kotlin 的协程Map<K,V>Flow<K,V>Spring中文文档

适用于 和 .Mono<Map<K,V>Flux<V>Spring中文文档

设置 Spring for GraphQL 的 Spring Boot 启动器会自动配置 for 虚拟线程。AnnotatedControllerConfigurerExecutorspring.threads.virtual.enabled

@GraphQlExceptionHandler

使用方法处理数据提取中的异常 灵活的方法签名。当在 controller,异常处理程序方法适用于来自同一控制器的异常:@GraphQlExceptionHandlerSpring中文文档

@Controller
public class BookController {

	@QueryMapping
	public Book bookById(@Argument Long id) {
		// ...
	}

	@GraphQlExceptionHandler
	public GraphQLError handle(BindException ex) {
		return GraphQLError.newError().errorType(ErrorType.BAD_REQUEST).message("...").build();
	}
}

当在 中声明时,异常处理程序方法跨控制器应用:@ControllerAdviceSpring中文文档

@ControllerAdvice
public class GlobalExceptionHandler {

	@GraphQlExceptionHandler
	public GraphQLError handle(BindException ex) {
		return GraphQLError.newError().errorType(ErrorType.BAD_REQUEST).message("...").build();
	}

}

通过方法进行异常处理会自动应用于 控制器调用。若要处理来自其他实现(而不是基于控制器方法)的异常,请获取 from ,并将其注册为 DataFetcherExceptionResolver@GraphQlExceptionHandlergraphql.schema.DataFetcherDataFetcherExceptionResolverAnnotatedControllerConfigurerGraphQlSource.BuilderSpring中文文档

方法签名

异常处理程序方法支持具有方法参数的灵活方法签名 从 A 解析并匹配到 @SchemaMapping 方法DataFetchingEnvironment,Spring中文文档

下面列出了支持的返回类型:Spring中文文档

返回类型 描述

graphql.GraphQLErrorSpring中文文档

解决单个字段错误的异常。Spring中文文档

Collection<GraphQLError>Spring中文文档

解决多个字段错误的异常。Spring中文文档

voidSpring中文文档

解决异常,无响应错误。Spring中文文档

ObjectSpring中文文档

将异常解决为单个错误、多个错误或无错误。 返回值必须为 、 或 。GraphQLErrorCollection<GraphQLError>nullSpring中文文档

Mono<T>Spring中文文档

对于异步解析,其中 是受支持的同步返回类型之一。<T>Spring中文文档

返回类型 描述

graphql.GraphQLErrorSpring中文文档

解决单个字段错误的异常。Spring中文文档

Collection<GraphQLError>Spring中文文档

解决多个字段错误的异常。Spring中文文档

voidSpring中文文档

解决异常,无响应错误。Spring中文文档

ObjectSpring中文文档

将异常解决为单个错误、多个错误或无错误。 返回值必须为 、 或 。GraphQLErrorCollection<GraphQLError>nullSpring中文文档

Mono<T>Spring中文文档

对于异步解析,其中 是受支持的同步返回类型之一。<T>Spring中文文档

命名空间

在架构级别,查询和变更操作直接在 和 类型下定义。 丰富的 GraphQL API 可以在这些类型下定义数十种操作,这使得探索 API 和分离关注点变得更加困难。 您可以选择在 GraphQL 架构中定义命名空间。 虽然这种方法有一些注意事项,但您可以使用 Spring for GraphQL 注释控制器实现此模式。QueryMutationSpring中文文档

例如,使用命名空间,您的 GraphQL 架构可以将查询操作嵌套在顶级类型下,而不是直接将它们列在 . 在这里,我们将定义和类型,并使它们在以下情况下可用:QueryMusicQueriesUserQueriesQuerySpring中文文档

type Query {
    music: MusicQueries
    users: UserQueries
}

type MusicQueries {
    album(id: ID!): Album
    searchForArtist(name: String!): [Artist]
}

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

type Artist {
    id: ID!
    name: String!
}

type UserQueries {
    user(login: String): User
}

type User {
    id: ID!
    login: String!
}

GraphQL 客户端将使用如下查询:albumSpring中文文档

{
  music {
    album(id: 42) {
      id
      title
    }
  }
}

并得到以下响应:Spring中文文档

{
  "data": {
    "music": {
      "album": {
        "id": "42",
        "title": "Spring for GraphQL"
      }
    }
  }
}

这可以通过以下模式实现:@ControllerSpring中文文档

import java.util.List;

import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;

@Controller
@SchemaMapping(typeName = "MusicQueries") (1)
public class MusicController {

	@QueryMapping (2)
	public MusicQueries music() {
		return new MusicQueries();
	}

	(3)
	public record MusicQueries() {

	}

	@SchemaMapping (4)
	public Album album(@Argument String id) {
		return new Album(id, "Spring GraphQL");
	}

	@SchemaMapping
	public List<Artist> searchForArtist(@Argument String name) {
		return List.of(new Artist("100", "the Spring team"));
	}


}
1 使用 和 属性对控制器进行批注,以避免在方法上重复它@SchemaMappingtypeName
2 为“music”命名空间定义一个@QueryMapping
3 “music”查询返回“空”记录,但也可能返回空地图
4 查询现在声明为“MusicQueries”类型下的字段

而不是在控制器中显式声明包装类型(“MusicQueries”、“UserQueries”), 您可以选择使用带有 Spring Boot 的运行时布线来配置它们:GraphQlSourceBuilderCustomizerSpring中文文档

import java.util.Collections;
import java.util.List;

import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class NamespaceConfiguration {

	@Bean
	public GraphQlSourceBuilderCustomizer customizer() {
		List<String> queryWrappers = List.of("music", "users"); (1)

		return (sourceBuilder) -> sourceBuilder.configureRuntimeWiring((wiringBuilder) ->
				queryWrappers.forEach((field) -> wiringBuilder.type("Query",
						(builder) -> builder.dataFetcher(field, (env) -> Collections.emptyMap()))) (2)
		);
	}

}
1 列出“查询”类型的所有包装器类型
2 为每个站点手动声明数据获取器,返回一个空的 Map
1 使用 和 属性对控制器进行批注,以避免在方法上重复它@SchemaMappingtypeName
2 为“music”命名空间定义一个@QueryMapping
3 “music”查询返回“空”记录,但也可能返回空地图
4 查询现在声明为“MusicQueries”类型下的字段
1 列出“查询”类型的所有包装器类型
2 为每个站点手动声明数据获取器,返回一个空的 Map