Spring for GraphQL入门教程(二)

2022-12-06 19:19:30 来源:51CTO博客

5. 带注释的控制者

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


(资料图片)

@Controllerpublic class GreetingController {        @QueryMapping         public String hello() {             return "Hello, world!";        }}

将此方法绑定到查询,即查询类型下的字段。

如果未在批注中声明,则根据方法名称确定查询。

Spring for GraphQL 用于将上述处理程序方法注册为名为 “hello” 的查询。​​RuntimeWiring.Builder​​​​graphql.schema.DataFetcher​

5.1. 声明

您可以将豆类定义为标准的春豆定义。刻板印象允许自动检测,与弹簧常规对齐 支持类路径上的检测和类 自动注册它们的 Bean 定义。它还充当注释的刻板印象 类,指示它在 GraphQL 应用程序中作为数据获取组件的角色。​​@Controller​​​​@Controller​​​​@Controller​​​​@Component​

​AnnotatedControllerConfigurer​​检测豆类并注册其 带注释的处理程序方法 ass via。这是一个 可以添加其中的实现。 Spring 引导启动器自动声明为 bean 并添加所有豆子,使 支持注释,请参阅GraphQL 运行时连接部分 在引导启动器文档中。​​@Controller​​​​DataFetcher​​​​RuntimeWiring.Builder​​​​RuntimeWiringConfigurer​​​​GraphQlSource.Builder​​​​AnnotatedControllerConfigurer​​​​RuntimeWiringConfigurer​​​​GraphQlSource.Builder​​​​DataFetcher​

5.2.​​@SchemaMapping​

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

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

注释也可以省略这些属性,在这种情况下, 字段名称默认为方法名称,而类型名称默认为简单类 注入到方法中的源/父对象的名称。例如,下面 默认键入“书籍”和字段“作者”:​​@SchemaMapping​

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

可以在类级别声明注释以指定默认值 类中所有处理程序方法的类型名称。​​@SchemaMapping​

@Controller@SchemaMapping(typeName="Book")public class BookController {    // @SchemaMapping methods for fields of the "Book" type}

​@QueryMapping​​,,和是元注释 本身带有注释,并将“字体名称”预设为 、、 或分别。实际上,这些是快捷方式注释 分别用于“查询”、“变更”和“订阅类型”下的字段。例如:​​@MutationMapping​​​​@SubscriptionMapping​​​​@SchemaMapping​​​​Query​​​​Mutation​​​​Subscription​

@Controllerpublic class BookController {    @QueryMapping    public Book bookById(@Argument Long id) {        // ...    }    @MutationMapping    public Book addBook(@Argument BookInput bookInput) {        // ...    }    @SubscriptionMapping    public Flux newPublications() {        // ...    }}

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

5.2.1. 方法签名

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

方法参数

描述

​@Argument​

用于访问绑定到更高级别类型化对象的命名字段参数。 看@Argument。

​@Argument Map

对于访问参数的原始映射,其中没有属性。​​@Argument​​​​name​

​ArgumentValue​

用于访问绑定到更高级别、键入的 Object 的命名字段参数 带有一个标志,用于指示输入参数是省略还是设置为。 请参阅参数值​。​​null​

​@Arguments​

用于访问绑定到更高级别的类型化对象的所有字段参数。 看@Arguments。

​@Arguments Map

用于访问参数的原始映射。

​@ProjectedPayload​​接口

用于通过项目界面访问字段参数。 请参阅@ProjectedPayload界面。

“来源”

用于访问字段的源(即父/容器)实例。 请参阅​​来源​​。

​DataLoader​

为了访问。 请参阅数据加载器​。​​DataLoader​​​​DataLoaderRegistry​

​@ContextValue​

用于从主界面访问属性。​​GraphQLContext​​​​DataFetchingEnvironment​

​@LocalContextValue​

用于从本地访问属性。​​GraphQLContext​​​​DataFetchingEnvironment​

​GraphQLContext​

用于从上下文访问。​​DataFetchingEnvironment​

​java.security.Principal​

从 Spring 安全性上下文(如果可用)获取。

​@AuthenticationPrincipal​

用于从 Spring 安全性上下文访问。​​Authentication#getPrincipal()​

​DataFetchingFieldSelectionSet​

用于访问用于查询的选择集。​​DataFetchingEnvironment​

​Locale​​​,​​Optional

用于访问从。​​Locale​​​​DataFetchingEnvironment​

​DataFetchingEnvironment​

用于直接访问底层证券。​​DataFetchingEnvironment​

架构映射处理程序方法可以返回:

任何类型的解析值。​​Mono​​和异步值。支持控制器方法和ReactiveDataFetcher中描述的 anyas。FluxDataFetcher​java.util.concurrent.Callable​​异步生成值。 为此,必须配置一个。AnnotatedControllerConfigurerExecutor

5.2.2.​​@Argument​

在 GraphQL Java 中,提供对特定于字段的映射的访问 参数值。这些值可以是简单的标量值(例如字符串、长整型)、aof 更复杂输入的值或 AOF 值。​​DataFetchingEnvironment​​​​Map​​​​List​

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

@Controllerpublic class BookController {    @QueryMapping    public Book bookById(@Argument Long id) {        // ...    }    @MutationMapping    public Book addBook(@Argument BookInput bookInput) {        // ...    }}

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

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

如果绑定失败,则引发绑定问题累积为字段 错误,其中每个错误都是出现问题的参数路径。​​BindException​​​​field​

您可以使用参数,获得原始地图 所有参数值。不得设置 name 属性 on。​​@Argument​​​​Map​​​@Argument​

5.2.3.​​ArgumentValue​

默认情况下,GraphQL 中的输入参数可为空且可选,这意味着参数 可以设置为文字,也可以根本不提供。这种区别对于 带有突变的部分更新,其中基础数据也可能是,设置为或根本不相应地更改。使用时@Argument没有办法进行这样的区分,因为在这两种情况下您都会得到一个空。​​null​​​​null​​​​null​​​​Optional​

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

例如:

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

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

5.2.4.​​@Arguments​

如果要将完整的参数映射绑定到单个参数映射上,请使用注释 目标对象,相反,它绑定特定的命名参数。​​@Arguments​​​​@Argument​

例如,使用参数“bookInput”的值 初始化,同时使用完整的参数映射,并在其中 在这种情况下,顶级参数绑定到属性。​​@Argument BookInput bookInput​​​​BookInput​​​​@Arguments​​​​BookInput​

您可以使用参数,获得原始地图 所有参数值。​​@Arguments​​​​Map

5.2.5.接口​​@ProjectedPayload​

作为将完整对象与@Argument一起使用的替代方法, 您还可以使用投影接口通过 定义明确,最小的接口。当 Spring 数据位于类路径上时,参数投影由Spring Data 的接口投影提供。

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

例如:

@Controllerpublic class BookController {    @QueryMapping    public Book bookById(BookIdProjection bookId) {        // ...    }    @MutationMapping    public Book addBook(@Argument BookInputProjection bookInput) {        // ...    }}@ProjectedPayloadinterface BookIdProjection {    Long getId();}@ProjectedPayloadinterface BookInputProjection {    String getName();    @Value("#{target.author + " " + target.name}")    String getAuthorAndName();}

5.2.6. 来源

在 GraphQL Java 中,提供对源代码的访问(即 父/容器)字段实例。要访问它,只需声明一个方法参数 预期的目标类型。​​DataFetchingEnvironment​

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

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

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

5.2.7.​​DataLoader​

当您为实体注册批处理加载函数时,如批处理加载中所述,您可以通过声明 类型的方法参数并使用它来加载实体:​​DataLoader​​​​DataLoader​

@Controllerpublic class BookController {    public BookController(BatchLoaderRegistry registry) {        registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {            // return Map        });    }    @SchemaMapping    public CompletableFuture author(Book book, DataLoader loader) {        return loader.load(book.getAuthorId());    }}

默认情况下,使用值类型的完整类名(例如 类名 for) 作为注册的密钥,因此只需声明 具有泛型类型的方法参数提供了足够的信息 以在 中找到它。作为回退,方法参数 解析器还将尝试将方法参数名称作为键,但通常不应 是必要的。​​BatchLoaderRegistry​​​​Author​​​​DataLoader​​​​DataLoaderRegistry​​​​DataLoader​

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

5.2.8. 验证

找到 abean 后,启用对带注释的控制器方法的Bean 验证支持。通常,Bean 属于类型。​​javax.validation.Validator​​​​AnnotatedControllerConfigurer​​​​LocalValidatorFactoryBean​

Bean 验证允许您声明对类型的约束:

public class BookInput {    @NotNull    private String title;    @NotNull    @Size(max=13)    private String isbn;}

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

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

如果在验证过程中发生错误,则会引发 ais 。 可以使用异常解析链来决定如何将其呈现给客户端 通过将其转换为要包含在 GraphQL 响应中的错误。​​ConstraintViolationException​

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

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

验证和 Kotlin 协程

休眠验证器与 Kotlin 协程方法不兼容,并且在以下情况下失败 反省其方法参数。请参阅spring-projects/spring-graphql#344 (comment)以获取相关问题的链接和建议的解决方法。

5.3.​​@BatchMapping​

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

@Controllerpublic class BookController {    public BookController(BatchLoaderRegistry registry) {        registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {            // return Map        });    }    @SchemaMapping    public CompletableFuture author(Book book, DataLoader loader) {        return loader.load(book.getAuthorId());    }}

对于加载关联实体的直接情况,如上所示,该方法只不过是委托给。这是 可以用方法避免的样板。例如:​​@SchemaMapping​​​​DataLoader​​​​@BatchMapping​

@Controllerpublic class BookController {    @BatchMapping    public Mono> author(List books) {        // ...    }}

上面成为其中键实例中的批量加载函数,加载的值是它们的作者。此外,ais 还透明地绑定到该类型的字段,其中 只是委托给 for 作者,给定其源/父实例。​​BatchLoaderRegistry​​​​Book​​​​DataFetcher​​​​author​​​​Book​​​​DataLoader​​​​Book​

要用作唯一键,必须实现和。​​Book​​​​hashcode​​​​equals​

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

5.3.1. 方法签名

批处理映射方法支持以下参数:

方法参数

描述

​List

源/父对象。

​java.security.Principal​

从 Spring 安全性上下文(如果可用)获取。

​@ContextValue​

为了访问来自 theof 的值, 这与来自的上下文相同。​​GraphQLContext​​​​BatchLoaderEnvironment​​​​DataFetchingEnvironment​

​GraphQLContext​

要从上下文访问, 这与来自的上下文相同。​​BatchLoaderEnvironment​​​​DataFetchingEnvironment​

​BatchLoaderEnvironment​

在 GraphQL Java 中可用的环境。​​org.dataloader.BatchLoaderWithContext​


标签: 处理程序 开始使用 您还可以

上一篇:天天微头条丨#yyds干货盘点# 名企真题专题:最大乘积
下一篇:全球观察:redis活跃非活跃连接数统计及client list说明