Spring for GraphQL入門

2022-12-06 18:05:28 來源:51CTO博客

1. 概述

Spring for GraphQL 為基于GraphQL Java構建的 Spring 應用程序提供支持。這是 GraphQL Java 團隊和 Spring 工程。


(資料圖片僅供參考)

Spring for GraphQL 是GraphQL Java Spring項目的繼承者,來自 GraphQL Java 團隊。它的目標是成為所有 Spring、GraphQL 應用程序的基礎。

請使用我們的問題跟蹤器報告問題、討論設計問題或請求功能。

請參閱我們的維基。 了解新增功能、基線要求、升級說明以及其他跨版本信息。

要開始使用,請查看 Spring GraphQL 入門on start.spring.io和Samples。

2. 服務器傳輸

Spring for GraphQL 支持服務器通過 HTTP、WebSocket 和 RSocket。

2.1. HTTP

??GraphQlHttpHandler??通過 HTTP 請求處理 GraphQL 并委托給攔截鏈以執行請求。有兩種變體,一種用于 Spring MVC 和一個用于 Spring WebFlux 的 MVC。兩者都異步處理請求,并且具有 等效的功能,但分別依賴于阻塞和非阻塞 I/O 編寫 HTTP 響應。

請求必須使用 HTTP POST,其中 GraphQL 請求詳細信息作為 JSON 包含在 請求正文,如提議的GraphQL over HTTP規范中所定義。成功解碼 JSON 正文后,HTTP 響應 狀態始終為 200(正常),并且 GraphQL 請求執行中的任何錯誤都顯示在 GraphQL 響應的“錯誤”部分。媒體類型的默認和首選選擇是,但也受支持,如中所述 規范。??"application/graphql+json"????"application/json"??

??GraphQlHttpHandler??可以通過聲明 abean 并使用 Spring MVC 或 WebFlux 創建路由來公開為 HTTP 端點。這 啟動啟動器執行此操作,請參閱Web 終結點部分 實際配置的詳細信息或檢查包含的內容。??RouterFunction????RouterFunctions????GraphQlWebMvcAutoConfiguration????GraphQlWebFluxAutoConfiguration??

Spring for GraphQL 存儲庫包含一個 Spring MVCHTTP 示例應用程序。

2.2. 網絡套接字

??GraphQlWebSocketHandler??根據graphql-ws庫中定義的協議處理 WebSocket 上的 GraphQL 請求。使用的主要原因 GraphQL over WebSocket 是允許發送 GraphQL 流的訂閱。 響應,但它也可以用于具有單個響應的常規查詢。 處理程序將每個請求委托給攔截鏈,以便進一步 請求執行。

GraphQL over WebSocket Protocol

有兩個這樣的協議,一個在subscriptions-transport-ws?庫中,另一個在graphql-ws?庫中。前者不活躍且 后者繼任。閱讀這篇博文了解歷史。

有兩種變體,一種用于Spring MVC,一種用于 Spring WebFlux.兩者都異步處理請求,并具有等效的功能。 WebFlux 處理程序還使用非阻塞 I/O 和背壓來流式傳輸消息, 這很好用,因為在 GraphQL Java 中,訂閱響應是反應式流。??GraphQlWebSocketHandler????Publisher??

該項目列出了許多供客戶使用的配方。??graphql-ws??

??GraphQlWebSocketHandler??可以通過聲明 abean 并使用它來將處理程序映射到 URL 路徑,將其公開為 WebSocket 終結點。默認情況下, 啟動啟動器不會通過 WebSocket 端點公開 GraphQL,但很容易 通過為終結點路徑添加屬性來啟用它。有關詳細信息,請參閱Web 端點部分,或查看實際的啟動啟動器配置。??SimpleUrlHandlerMapping????GraphQlWebMvcAutoConfiguration????GraphQlWebFluxAutoConfiguration??

Spring for GraphQL 存儲庫包含一個WebFlux WebSocket 示例應用程序。

2.3. RSocket

??GraphQlRSocketHandler??通過 RSocket 請求處理 GraphQL。查詢和突變是 預期并作為 RSocket 交互處理,而訂閱 處理為。??request-response????request-stream??

??GraphQlRSocketHandler??可以使用映射到的 ana 中的委托 GraphQL 請求的路由。例如:??@Controller??

@Controllerpublic class GraphQlRSocketController {     private final GraphQlRSocketHandler handler;     GraphQlRSocketController(GraphQlRSocketHandler handler) {            this.handler = handler;     }     @MessageMapping("graphql")     public Mono> handle(Map payload) {            return this.handler.handle(payload);     }     @MessageMapping("graphql")     public Flux> handleSubscription(Map payload) {            return this.handler.handleSubscription(payload);     }}

2.4. 攔截

服務器傳輸允許在 GraphQL Java 引擎之前和之后攔截請求 調用以處理請求。

2.4.1.??WebGraphQlInterceptor??

HTTP和WebSocket傳輸調用鏈 0 或更多,后跟一個調用 GraphQL Java 引擎允許應用程序攔截 傳入請求,然后執行以下操作之一:??WebGraphQlInterceptor????ExecutionGraphQlService????WebGraphQlInterceptor??

檢查 HTTP 請求詳細信息自定義graphql.ExecutionInput添加 HTTP 響應標頭自定義graphql.ExecutionResult

例如,攔截器可以將 HTTP 請求標頭傳遞給:??DataFetcher??

class HeaderInterceptor implements WebGraphQlInterceptor {     @Override    public Mono intercept(WebGraphQlRequest request, Chain chain) {        String value = request.getHeaders().getFirst("myHeader");        request.configureExecutionInput((executionInput, builder) ->                builder.graphQLContext(Collections.singletonMap("myHeader", value)).build());        return chain.next(request);    }}@Controllerclass MyController {     @QueryMapping    Person person(@ContextValue String myHeader) {        // ...    }}

攔截器將 HTTP 請求標頭值添加到 GraphQLContext 中

數據控制器方法訪問值

相反,攔截器可以訪問控制器添加到的值:??GraphQLContext??

@Controllerclass MyController {    @QueryMapping    Person person(GraphQLContext context) {         context.put("cookieName", "123");    }}// Subsequent access from a WebGraphQlInterceptorclass HeaderInterceptor implements WebGraphQlInterceptor {    @Override    public Mono intercept(WebGraphQlRequest request, Chain chain) {         return chain.next(request).doOnNext(response -> {            String value = response.getExecutionInput().getGraphQLContext().get("cookieName");            ResponseCookie cookie = ResponseCookie.from("cookieName", value).build();            response.getResponseHeaders().add(HttpHeaders.SET_COOKIE, cookie.toString());        });    }}

控制器為??GraphQLContext??

攔截器使用該值添加 HTTP 響應標頭

??WebGraphQlHandler??可以修改,例如,檢查和修改 請求驗證錯誤,這些錯誤在執行開始之前引發,并且不能 處理方式為:??ExecutionResult????DataFetcherExceptionResolver??

static class RequestErrorInterceptor implements WebGraphQlInterceptor {    @Override    public Mono intercept(WebGraphQlRequest request, Chain chain) {        return chain.next(request).map(response -> {            if (response.isValid()) {                return response;             }            List errors = response.getErrors().stream()                     .map(error -> {                        GraphqlErrorBuilder builder = GraphqlErrorBuilder.newError();                        // ...                        return builder.build();                    })                    .collect(Collectors.toList());            return response.transform(builder -> builder.errors(errors).build());         });    }}

返回相同的 ifhas 具有非空值的“data”鍵??ExecutionResult??

檢查并轉換 GraphQL 錯誤

更新修改后的錯誤??ExecutionResult??

用于配置鏈。這是支持的 通過啟動啟動器,請參閱Web 終結點。??WebGraphQlHandler????WebGraphQlInterceptor??

2.4.2.??RSocketQlInterceptor??

與WebGraphQlInterceptor類似,允許攔截 GraphQL 在 GraphQL Java 引擎執行之前和之后通過 RSocket 請求。您可以使用 這要定制和的。??RSocketQlInterceptor????graphql.ExecutionInput????graphql.ExecutionResult??

3. 請求執行

??ExecutionGraphQlService??是調用 GraphQL Java 來執行的主要 Spring 抽象 請求。基礎傳輸(如服務器傳輸)委托 toto 處理請求。??ExecutionGraphQlService??

主實現配置了對要調用的實例的 afor 訪問。??DefaultExecutionGraphQlService????GraphQlSource????graphql.GraphQL??

3.1.??GraphQLSource??

??GraphQlSource??是一個合約,用于公開實例以使用它 包括用于構建該實例的構建器 API。默認構建器可通過 a 使用。Spring 引導啟動器創建 此生成器并進一步初始化它,如下所示:??graphql.GraphQL????GraphQlSource.schemaResourceBuilder()??

從可配置位置加載架構文件。公開適用于的屬性。GraphQlSource.Builder檢測運行時布線配置器bean。檢測GraphQL 指標的檢測 bean。檢測 bean 以解決異常。DataFetcherExceptionResolver檢測訂閱異常解析。SubscriptionExceptionResolver

對于進一步的自定義,您可以聲明 abean。例如,到 配置您自己的:??GraphQlSourceBuilderCustomizer????ExecutionIdProvider??

@Configuration(proxyBeanMethods = false)class GraphQlConfig {    @Bean    public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {        return (builder) ->                builder.configureGraphQl(graphQlBuilder ->                        graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));    }}

3.1.1. 模式資源

??GraphQlSource.Builder??可以配置一個或多個實例 解析并合并在一起。這意味著架構文件可以從幾乎任何 位置。??Resource??

默認情況下,Spring 引導啟動器會查找帶有擴展名的模式文件位置下的“.graphqls”或“.gqls”,這是典型的。您還可以使用文件系統位置或任何位置 由 Springhierarchy 支持,包括一個自定義實現 從遠程位置、存儲或內存加載架構文件。??classpath:graphql/**????src/main/resources/graphql????Resource??

用于跨多個類路徑查找架構文件 位置,例如跨多個模塊。??classpath*:graphql/**/??

3.1.2. 模式創建

默認情況下,使用 GraphQL Java 來創建。這適用于典型用途,但如果您需要使用 不同的生成器,例如對于聯合,您可以注冊回調:??GraphQlSource.Builder????SchemaGenerator????graphql.schema.GraphQLSchema????schemaFactory??

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

GraphQlSource部分解釋了如何使用Spring Boot進行配置。

3.1.3. 模式遍歷

如果您想在之后遍歷架構,您可以注冊 aviaif 它已創建,并可能將更改應用于。請記住, 但是,此類訪問者無法更改架構。如果需要對架構進行更改,請參閱架構轉換。??graphql.schema.GraphQLTypeVisitor????builder.schemaResources(..).typeVisitors(..)????GraphQLCodeRegistry??

3.1.4. 模式轉換

您可以注冊 aviaif 如果您想遍歷 并在創建架構后對其進行轉換,并對架構進行更改。謹記 這通常比架構遍歷更昂貴 首選遍歷而不是轉換,除非需要進行架構更改。??graphql.schema.GraphQLTypeVisitor????builder.schemaResources(..).typeVisitorsToTransformSchema(..)??

3.1.5.??RuntimeWiringConfigurer??

您可以使用注冊:??RuntimeWiringConfigurer??

自定義標量類型。處理代碼的指令。??TypeResolver??,如果需要覆蓋某個類型的默認類型解析程序。??DataFetcher??對于一個字段,盡管大多數應用程序將簡單地配置,以檢測帶注釋的處理程序方法。 彈簧引導啟動器添加默認情況下。AnnotatedControllerConfigurerDataFetcherAnnotatedControllerConfigurer

與 Web 框架不同,GraphQL 不使用 Jackson 注釋來驅動 JSON 序列化/反序列化。 自定義數據類型及其序列化必須描述為標量。

Spring 引導啟動器檢測類型和 將它們注冊在。這意味著在大多數情況下,您將擁有 配置中類似于以下內容的內容:??RuntimeWiringConfigurer????GraphQlSource.Builder??

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

如果您需要添加 a,例如進行考慮到 架構定義,實現同時接受 THE 和 輸出的替代方法。這允許您添加任何 然后按順序調用的工廠數。??WiringFactory????configure????RuntimeWiring.Builder????List??

3.1.6. 默認值??TypeResolver??

??GraphQlSource.Builder??registersas defaultto 用于尚未具有此類注冊的 GraphQL 接口和聯合 通過運行時布線配置器。目的 ain GraphQL Java 是確定值的 GraphQL 對象類型 從 for GraphQL 接口或聯合字段返回。??ClassNameTypeResolver????TypeResolver????TypeResolver????DataFetcher??

??ClassNameTypeResolver??嘗試將值的簡單類名與 GraphQL 匹配 對象類型,如果不成功,它還導航其超類型,包括 基類和接口,查找匹配項。提供 選項以配置名稱提取函數以及 GraphQL 對象類型 名稱映射,應有助于涵蓋更多極端情況:??ClassNameTypeResolver????Class??

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

GraphQlSource部分解釋了如何使用Spring Boot進行配置。

3.1.7. 操作緩存

GraphQL Java 必須在執行操作之前對其進行解析驗證。這可能會影響 性能顯著。為了避免需要重新分析和驗證,應用程序可以 配置緩存和重用文檔實例。GraphQL Java 文檔提供了更多關于 通過 A 進行查詢緩存。??PreparsedDocumentProvider????PreparsedDocumentProvider??

在Spring GraphQL中,你可以通過以下方式注冊: .??PreparsedDocumentProvider????GraphQlSource.Builder#configureGraphQl??

// Typically, accessed through Spring Boot"s GraphQlSourceBuilderCustomizerGraphQlSource.Builder builder = ...// Create providerPreparsedDocumentProvider provider = ...builder.schemaResources(..)        .configureRuntimeWiring(..)        .configureGraphQl(graphQLBuilder -> graphQLBuilder.preparsedDocumentProvider(provider))

GraphQlSource部分解釋了如何使用Spring Boot進行配置。

3.1.8. 指令

GraphQL 語言支持“描述備用運行時執行和 GraphQL 文檔中的類型驗證行為”。指令類似于 中的注釋 Java 但在 GraphQL 文檔中對類型、字段、片段和操作聲明。

GraphQL Java 提供合約來幫助應用程序檢測 并處理指令。有關更多詳細信息,請參閱GraphQL Java 文檔。??SchemaDirectiveWiring??

在Spring GraphQL中,你可以通過RuntimeWiringConfigurer注冊。彈簧啟動啟動器檢測到 這樣的豆子,所以你可能會有這樣的東西:??SchemaDirectiveWiring??

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

有關指令支持的示例,請查看Extended Validation for Graphql Java庫。

3.2. 反應式??DataFetcher??

默認構建器啟用對 ato 返回器的支持,它使這些內容適應聚合值 并轉換為列表,除非請求是 GraphQL 訂閱請求, 在這種情況下,返回值仍然是 反應式流用于流式處理 GraphQL 響應。??GraphQlSource????DataFetcher????Mono????Flux????CompletableFuture????Flux????Publisher??

反應式可以依賴于對從 傳輸層,例如來自 WebFlux 請求處理,請參閱WebFlux 上下文。??DataFetcher??

3.3. 上下文傳播

Spring for GraphQL 支持通過 GraphQL Java 透明地傳播來自服務器傳輸的上下文,以及它和其他組件 調用。這包括來自Spring MVC請求處理的兩個上下文 線程和反應器來自 WebFlux 處理管道。??DataFetcher????ThreadLocal????Context??

3.3.1. 網絡媒體

A和 GraphQL Java 調用的其他組件可能并不總是在 與Spring MVC處理程序相同的線程,例如,如果異步WebGraphQlInterceptor或切換到 不同的線程。??DataFetcher????DataFetcher??

Spring for GraphQL 支持從 Servlet 容器傳播值 線程到線程 a 和 GraphQL Java 調用的其他組件到 繼續執行。為此,應用程序需要實現感興趣的值:??ThreadLocal????DataFetcher????io.micrometer.context.ThreadLocalAccessor????ThreadLocal??

public class RequestAttributesAccessor implements ThreadLocalAccessor {    @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();    }}

您可以在啟動時手動注冊全局實例,該實例可通過 a 訪問。您也可以注冊 自動通過機制。??ThreadLocalAccessor????ContextRegistry????io.micrometer.context.ContextRegistry#getInstance()????java.util.ServiceLoader??

3.3.2. 網絡通量

響應式數據獲取器可以依賴于對反應器上下文的訪問,該上下文 源自 WebFlux 請求處理鏈。這包括反應器上下文 由WebGraphQlInterceptor組件添加。

3.4. 異常解決

一個 GraphQL Java 應用程序可以注冊 ato 來決定如何 表示 GraphQL 響應的“錯誤”部分中數據層的異常。??DataFetcherExceptionHandler??

Spring for GraphQL 有一個內置的,配置為使用 默認的GraphQLSource構建器。它允許應用程序注冊 按順序調用的一個或多個 Spring組件 直到解析為(可能為空的)對象列表。??DataFetcherExceptionHandler????DataFetcherExceptionResolver????Exception????graphql.GraphQLError??

??DataFetcherExceptionResolver??是一個異步合約。對于大多數實現,它 將足以擴展和覆蓋 它的方法之一 同步解決異常。??DataFetcherExceptionResolverAdapter????resolveToSingleError????resolveToMultipleErrors??

A可以通過以下方式分配到類別。 在Spring GraphQL中,您還可以分配viawhich具有以下常見 應用程序可用于對錯誤進行分類的分類:??GraphQLError????graphql.ErrorClassification????ErrorType??

??BAD_REQUEST????UNAUTHORIZED????FORBIDDEN????NOT_FOUND????INTERNAL_ERROR??

如果異常仍未解決,則默認情況下,它被歸類為包含類別名稱和發件人的通用消息。消息故意不透明以避免泄漏 實現詳細信息。應用程序可以使用a來自定義 錯誤詳細信息。??INTERNAL_ERROR????executionId????DataFetchingEnvironment????DataFetcherExceptionResolver??

未解決的異常記錄在錯誤級別以及關聯 發送到客戶端的錯誤。已解決的異常記錄在調試級別。??executionId??

3.4.1. 請求異常

GraphQL Java 引擎在解析請求時可能會遇到驗證或其他錯誤 這反過來又會阻止請求執行。在這種情況下,響應包含 “data”鍵和一個或多個全局的請求級“錯誤”,即不是 具有字段路徑。??null??

??DataFetcherExceptionResolver??無法處理此類全局錯誤,因為它們被引發 在執行開始之前和調用 anyis 之前。應用程序可以使用 傳輸級攔截器來檢查和轉換錯誤。 請參閱WebGraphQlInterceptor下的示例。??DataFetcher????ExecutionResult??

3.4.2. 訂閱例外

對于訂閱請求可能會以錯誤信號完成,在這種情況下 底層傳輸(例如 WebSocket)發送帶有列表的最終“錯誤”類型消息 的 GraphQL 錯誤。??Publisher??

??DataFetcherExceptionResolver??無法解決訂閱中的錯誤, 由于數據僅創建初始。之后, 傳輸訂閱,然后可能會完成并顯示錯誤。??Publisher????DataFetcher????Publisher????Publisher??

應用程序可以注冊以解析 訂閱中的異常為了將這些異常解析為 GraphQL 錯誤 以發送到客戶端。??SubscriptionExceptionResolver????Publisher??

3.5. 批量加載

給定它,我們可以為一本書創建一個,另一個 為其作者。這允許選擇有或沒有作者的書籍,但這意味著書籍 并且作者沒有一起加載,這在查詢多個時效率特別低下 作為每本書作者的書籍是單獨加載的。這稱為 N+1 選擇 問題。??Book????Author????DataFetcher??

3.5.1.??DataLoader??

GraphQL Java 提供了一種批量加載相關實體的機制。 您可以在GraphQL Java 文檔中找到完整的詳細信息。下面是一個 工作原理摘要:??DataLoader??

注冊在可以加載實體,給定唯一鍵。DataLoaderDataLoaderRegistry??DataFetcher??可以訪問并使用它們按 ID 加載實體。DataLoader通過返回未來來延遲加載,以便可以批量完成。DataLoader??DataLoader??維護已加載實體的每請求緩存,這些緩存可以進一步 提高效率。

3.5.2.??BatchLoaderRegistry??

GraphQL Java 中的完整批處理加載機制需要實現以下之一 幾個接口,然后包裝和注冊那些屁股 有一個名字在。??BatchLoader????DataLoader????DataLoaderRegistry??

Spring GraphQL 中的 API 略有不同。對于注冊,只有一個, 集中公開工廠方法和構建器來創建和 注冊任意數量的批量加載函數:??BatchLoaderRegistry??

@Configurationpublic class MyConfig {    public MyConfig(BatchLoaderRegistry registry) {        registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {                // return Mono        });        // more registrations ...    }}

Spring Boot 啟動器聲明了您可以注入的 abean 您的配置,如上所示,或按順序放入任何組件(如控制器) 注冊批量加載函數。反過來,注入到確保每個請求注冊的地方。??BatchLoaderRegistry????BatchLoaderRegistry????DefaultExecutionGraphQlService????DataLoader??

默認情況下,名稱基于目標實體的類名。 這允許方法使用泛型類型聲明DataLoader 參數,并且 無需指定名稱。但是,如有必要,可以通過構建器以及其他名稱自定義名稱。??DataLoader????@SchemaMapping????BatchLoaderRegistry????DataLoaderOptions??

配置默認全局,用作任何 注冊,你可以覆蓋 Boot"sbean 并使用構造函數 為此接受。??DataLoaderOptions????BatchLoaderRegistry????DefaultBatchLoaderRegistry????Supplier??

在許多情況下,在加載相關實體時,可以使用@BatchMapping控制器方法,這是一種快捷方式 對于和替換需要使用和直接。??BatchLoaderRegistry????DataLoader??

??BatchLoaderRegistry??還提供其他重要的好處。它支持訪問 從批量加載函數和 from 方法相同, 以及確保上下文傳播到它們。這就是為什么需要應用程序的原因 來使用它。可以直接執行自己的注冊,但 此類注冊將放棄上述好處。??GraphQLContext????@BatchMapping????DataLoader??

3.5.3. 測試批量加載

首先在以下設備上執行注冊:??BatchLoaderRegistry????DataLoaderRegistry??

BatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();// perform registrations...DataLoaderRegistry dataLoaderRegistry = DataLoaderRegistry.newRegistry().build();batchLoaderRegistry.registerDataLoaders(dataLoaderRegistry, graphQLContext);

現在,您可以按如下方式訪問和測試個人:??DataLoader??

DataLoader loader = dataLoaderRegistry.getDataLoader(Book.class.getName());loader.load(1L);loader.loadMany(Arrays.asList(2L, 3L));List books = loader.dispatchAndJoin(); // actual loadingassertThat(books).hasSize(3);assertThat(books.get(0).getName()).isEqualTo("...");// ...

4. 數據集成

Spring for GraphQL 允許您利用現有的 Spring 技術,遵循常見的 編程模型以通過 GraphQL 公開底層數據源。

本節討論 Spring Data 的集成層,該集成層提供了一種簡單的方法來 將 Querydsl 或按示例查詢的存儲庫調整為 a,包括 用于自動檢測和 GraphQL 查詢注冊的選項,用于標記的存儲庫 跟。??DataFetcher????@GraphQlRepository??

4.1. 查詢

Spring for GraphQL 支持使用Querydsl通過 SpringData Querydsl擴展。 Querydsl 提供了一種靈活但類型安全的方法來表達查詢謂詞: 使用注釋處理器生成元模型。

例如,將存儲庫聲明為:??QuerydslPredicateExecutor??

public interface AccountRepository extends Repository,            QuerydslPredicateExecutor {}

然后使用它來創建:??DataFetcher??

// For single result queriesDataFetcher dataFetcher =        QuerydslDataFetcher.builder(repository).single();// For multi-result queriesDataFetcher> dataFetcher =        QuerydslDataFetcher.builder(repository).many();

您現在可以通過運行時布線配置器注冊上述內容。??DataFetcher??

構建一個 Querydslfrom GraphQL 請求參數,以及 使用它來獲取數據。Spring Data 支持 JPA, MongoDB和LDAP。??DataFetcher????Predicate????QuerydslPredicateExecutor??

如果存儲庫是,則構建器返回 sor。Spring Data支持這一點 MongoDB的變體。??ReactiveQuerydslPredicateExecutor????DataFetcher>????DataFetcher>??

4.1.1. 構建設置

要在構建中配置 Querydsl,請遵循官方參考文檔:

例如:

格拉德爾

馬文

dependencies {    //...    annotationProcessor "com.querydsl:querydsl-apt:$querydslVersion:jpa",            "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final",            "javax.annotation:javax.annotation-api:1.3.2"}compileJava {     options.annotationProcessorPath = configurations.annotationProcessor}

webmvc-http示例使用 Querydsl 進行。??artifactRepositories??

4.1.2. 自定義

??QuerydslDataFetcher??支持自定義如何將 GraphQL 參數綁定到屬性上 以創建查詢。默認情況下,參數綁定為“等于” 每個可用屬性。要自定義它,您可以使用構建器 提供的方法 a.??Predicate????QuerydslDataFetcher????QuerydslBinderCustomizer??

存儲庫本身可能是 的實例。這是自動檢測的 并在自動注冊期間透明應用。但是,當手動時 構建 Ayou 需要使用構建器方法來應用它。??QuerydslBinderCustomizer????QuerydslDataFetcher??

??QuerydslDataFetcher??支持接口和 DTO 投影以轉換查詢結果 在返回這些內容以進行進一步的 GraphQL 處理之前。

要了解什么是預測,請參閱Spring Data文檔?。 要了解如何在 GraphQL 中使用投影,請參閱選擇集與投影。

要將 Spring 數據投影與 Querydsl 存儲庫一起使用,請創建投影接口 或目標DTO類,并通過該方法對其進行配置,以獲得生成目標類型:??projectAs????DataFetcher??

class Account {    String name, identifier, description;    Person owner;}interface AccountProjection {    String getName();    String getIdentifier();}// For single result queriesDataFetcher dataFetcher =        QuerydslDataFetcher.builder(repository).projectAs(AccountProjection.class).single();// For multi-result queriesDataFetcher> dataFetcher =        QuerydslDataFetcher.builder(repository).projectAs(AccountProjection.class).many();

4.1.3. 自動注冊

如果存儲庫帶有注釋,則會自動注冊 對于尚未注冊且返回類型尚未注冊的查詢 與存儲庫域類型的匹配。這包括單值和多值 查詢。??@GraphQlRepository????DataFetcher??

默認情況下,查詢返回的 GraphQL 類型的名稱必須與簡單名稱匹配 存儲庫域類型。如果需要,可以使用屬性來指定目標 GraphQL 類型名稱。??typeName????@GraphQlRepository??

自動注冊檢測給定存儲庫是否實現和 通過構建器方法透明地應用該方法。??QuerydslBinderCustomizer????QuerydslDataFetcher??

自動注冊是通過內置的 從獲得。自動啟動啟動器檢測 bean 并使用它們來初始化。??RuntimeWiringConfigurer????QuerydslDataFetcher????@GraphQlRepository????RuntimeWiringConfigurer??

自動注冊不支持自定義。 如果你需要它,你需要使用構建和 通過運行時布線配置器手動注冊。??QueryByExampleDataFetcher????DataFetcher??

4.2. 示例查詢

Spring 數據支持使用示例查詢來獲取數據。按示例查詢 (QBE) 是一種簡單的查詢技術,不需要 通過特定于存儲的查詢語言編寫查詢。

首先聲明一個存儲庫,該存儲庫是:??QueryByExampleExecutor??

public interface AccountRepository extends Repository,            QueryByExampleExecutor {}

用于將存儲庫轉換為:??QueryByExampleDataFetcher????DataFetcher??

// For single result queriesDataFetcher dataFetcher =        QueryByExampleDataFetcher.builder(repository).single();// For multi-result queriesDataFetcher> dataFetcher =        QueryByExampleDataFetcher.builder(repository).many();

您現在可以通過運行時布線配置器注冊上述內容。??DataFetcher??

使用 GraphQL 參數映射來創建 存儲庫并將其用作獲取數據的示例對象。Spring Data 支持 JPA、MongoDB、Neo4j 和 Redis。??DataFetcher????QueryByExampleDataFetcher??

如果存儲庫是,則構建器返回 sor。Spring Data支持這一點 MongoDB,Neo4j,Redis和R2dbc的變體。??ReactiveQueryByExampleExecutor????DataFetcher>????DataFetcher>??

4.2.1. 構建設置

按示例查詢已包含在數據存儲的 Spring 數據模塊中,其中 它受支持,因此無需額外設置即可啟用它。

4.2.2. 自定義

??QueryByExampleDataFetcher??支持接口和DTO投影來轉換查詢 結果,然后再返回這些結果以進行進一步的 GraphQL 處理。

要了解什么是預測,請參閱Spring 數據文檔?。 要了解投影在 GraphQL 中的作用,請參閱選擇集與投影。

要將 Spring 數據投影與按示例查詢存儲庫一起使用,請創建投影接口 或目標DTO類,并通過該方法對其進行配置,以獲得生成目標類型:??projectAs????DataFetcher??

class Account {    String name, identifier, description;    Person owner;}interface AccountProjection {    String getName();    String getIdentifier();}// For single result queriesDataFetcher dataFetcher =        QueryByExampleDataFetcher.builder(repository).projectAs(AccountProjection.class).single();// For multi-result queriesDataFetcher> dataFetcher =        QueryByExampleDataFetcher.builder(repository).projectAs(AccountProjection.class).many();

4.2.3. 自動注冊

如果存儲庫帶有注釋,則會自動注冊 對于尚未注冊且返回類型尚未注冊的查詢 與存儲庫域類型的匹配。這包括單值和多值 查詢。??@GraphQlRepository????DataFetcher??

默認情況下,查詢返回的 GraphQL 類型的名稱必須與簡單名稱匹配 存儲庫域類型。如果需要,可以使用屬性來指定目標 GraphQL 類型名稱。??typeName????@GraphQlRepository??

自動注冊是通過內置的 從獲得。自動啟動啟動器檢測 bean 并使用它們來初始化。??RuntimeWiringConfigurer????QueryByExampleDataFetcher????@GraphQlRepository????RuntimeWiringConfigurer??

自動注冊不支持自定義。 如果你需要它,你需要使用構建和 通過運行時布線配置器手動注冊。??QueryByExampleDataFetcher????DataFetcher??

4.3. 選擇集與投影

出現的一個常見問題是,GraphQL 選擇集與Spring 數據投影相比如何,每個選擇集扮演什么角色?

簡短的回答是,Spring for GraphQL 不是一個翻譯 GraphQL 的數據網關。 直接查詢到 SQL 或 JSON 查詢中。相反,它可以讓您利用現有的Spring。 技術,并且不假設 GraphQL 模式和 基礎數據模型。這就是客戶端驅動的選擇和服務器端轉換的原因 的數據模型可以起到互補的作用。

為了更好地理解,請考慮Spring Data將域驅動(DDD)設計推廣為: 管理數據層復雜性的推薦方法。在 DDD 中,重要的是 遵守聚合的約束。根據定義,聚合僅在以下情況下有效 完全加載,因為部分加載的聚合可能會對 聚合功能。

在 Spring 數據中,您可以選擇是希望按原樣公開聚合,還是 是否在將數據模型作為 GraphQL 返回之前對數據模型應用轉換 結果。有時做前者就足夠了,默認情況下,Querydsl和按示例查詢集成會轉動GraphQL 選擇集到屬性路徑提示,底層 Spring 數據模塊用于 限制選擇。

在其他情況下,減少甚至轉換基礎數據模型很有用 以適應 GraphQL 模式。Spring Data通過接口支持這一點 和 DTO 預測。

接口投影定義一組固定的屬性,以公開屬性可能或 可能不是,具體取決于數據存儲查詢結果。有兩種 接口投影兩者都確定要從底層加載哪些屬性 數據來源:??null??

如果無法部分具體化聚合對象,但仍然 想要公開屬性的子集。開放接口投影利用 Spring 的 sannotation 和SpEL表達式來應用輕量級 數據轉換,例如串聯、計算或應用靜態函數 到屬性。@Value

DTO投影提供更高級別的自定義,因為您可以放置轉換 在構造函數或 getter 方法中編寫代碼。

DTO 投影從各個屬性所在的查詢中具體化 由投影本身決定。DTO投影通常與全參數一起使用 構造函數(例如 Java 記錄),因此它們只能在所有情況下構造 必填字段(或列)是數據庫查詢結果的一部分。

標簽: 應用程序 詳細信息 可以使用

上一篇:環球微資訊!Spring Session for Apache Geode 教程
下一篇:常見排序功能的實現