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說明