首页 > 其他分享 >Spring for GraphQL入门

Spring for GraphQL入门

时间:2022-12-06 17:31:09浏览次数:46  
标签:Java 入门 DataFetcher Spring builder GraphQL 注册

Spring for GraphQL入门_Java

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​

@Controller
public class GraphQlRSocketController {

private final GraphQlRSocketHandler handler;

GraphQlRSocketController(GraphQlRSocketHandler handler) {
this.handler = handler;
}

@MessageMapping("graphql")
public Mono<Map<String, Object>> handle(Map<String, Object> payload) {
return this.handler.handle(payload);
}

@MessageMapping("graphql")
public Flux<Map<String, Object>> handleSubscription(Map<String, Object> 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<WebGraphQlResponse> 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);
}
}

@Controller
class MyController {

@QueryMapping
Person person(@ContextValue String myHeader) {
// ...
}
}

拦截器将 HTTP 请求标头值添加到 GraphQLContext 中

数据控制器方法访问值

相反,拦截器可以访问控制器添加到的值:​​GraphQLContext​

@Controller
class MyController {

@QueryMapping
Person person(GraphQLContext context) {
context.put("cookieName", "123");
}
}

// Subsequent access from a WebGraphQlInterceptor

class HeaderInterceptor implements WebGraphQlInterceptor {

@Override
public Mono<WebGraphQlResponse> 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<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
return chain.next(request).map(response -> {
if (response.isValid()) {
return response;
}

List<GraphQLError> 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​

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

如果您需要添加 a,例如进行考虑到 架构定义,实现同时接受 THE 和 输出的替代方法。这允许您添加任何 然后按顺序调用的工厂数。​​WiringFactory​​​​configure​​​​RuntimeWiring.Builder​​​​List<WiringFactory>​

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 GraphQlSourceBuilderCustomizer
GraphQlSource.Builder builder = ...

// Create provider
PreparsedDocumentProvider 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​

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

}

您可以在启动时手动注册全局实例,该实例可通过 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​

  1. 注册在可以加载实体,给定唯一键。DataLoaderDataLoaderRegistry
  2. ​DataFetcher​​可以访问并使用它们按 ID 加载实体。DataLoader
  3. 通过返回未来来延迟加载,以便可以批量完成。DataLoader
  4. ​DataLoader​​维护已加载实体的每请求缓存,这些缓存可以进一步 提高效率。

3.5.2. ​​BatchLoaderRegistry​

GraphQL Java 中的完整批处理加载机制需要实现以下之一 几个接口,然后包装和注册那些屁股 有一个名字在。​​BatchLoader​​​​DataLoader​​​​DataLoaderRegistry​

Spring GraphQL 中的 API 略有不同。对于注册,只有一个, 集中公开工厂方法和构建器来创建和 注册任意数量的批量加载函数:​​BatchLoaderRegistry​

@Configuration
public class MyConfig {

public MyConfig(BatchLoaderRegistry registry) {

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

// more registrations ...
}

}

Spring Boot 启动器声明了您可以注入的 abean 您的配置,如上所示,或按顺序放入任何组件(如控制器) 注册批量加载函数。反过来,注入到确保每个请求注册的地方。​​BatchLoaderRegistry​​​​BatchLoaderRegistry​​​​DefaultExecutionGraphQlService​​​​DataLoader​

默认情况下,名称基于目标实体的类名。 这允许方法使用泛型类型声明DataLoader 参数,并且 无需指定名称。但是,如有必要,可以通过构建器以及其他名称自定义名称。​​DataLoader​​​​@SchemaMapping​​​​BatchLoaderRegistry​​​​DataLoaderOptions​

配置默认全局,用作任何 注册,你可以覆盖 Boot'sbean 并使用构造函数 为此接受。​​DataLoaderOptions​​​​BatchLoaderRegistry​​​​DefaultBatchLoaderRegistry​​​​Supplier<DataLoaderOptions>​

在许多情况下,在加载相关实体时,可以使用@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<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("...");
// ...

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<Account, Long>,
QuerydslPredicateExecutor<Account> {
}

然后使用它来创建:​​DataFetcher​

// For single result queries
DataFetcher<Account> dataFetcher =
QuerydslDataFetcher.builder(repository).single();

// For multi-result queries
DataFetcher<Iterable<Account>> dataFetcher =
QuerydslDataFetcher.builder(repository).many();

您现在可以通过运行时布线配置器注册上述内容。​​DataFetcher​

构建一个 Querydslfrom GraphQL 请求参数,以及 使用它来获取数据。Spring Data 支持 JPA, MongoDB和LDAP。​​DataFetcher​​​​Predicate​​​​QuerydslPredicateExecutor​

如果存储库是,则构建器返回 sor。Spring Data支持这一点 MongoDB的变体。​​ReactiveQuerydslPredicateExecutor​​​​DataFetcher<Mono<Account>>​​​​DataFetcher<Flux<Account>>​

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 queries
DataFetcher<AccountProjection> dataFetcher =
QuerydslDataFetcher.builder(repository).projectAs(AccountProjection.class).single();

// For multi-result queries
DataFetcher<Iterable<AccountProjection>> 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<Account, Long>,
QueryByExampleExecutor<Account> {
}

用于将存储库转换为:​​QueryByExampleDataFetcher​​​​DataFetcher​

// For single result queries
DataFetcher<Account> dataFetcher =
QueryByExampleDataFetcher.builder(repository).single();

// For multi-result queries
DataFetcher<Iterable<Account>> dataFetcher =
QueryByExampleDataFetcher.builder(repository).many();

您现在可以通过运行时布线配置器注册上述内容。​​DataFetcher​

使用 GraphQL 参数映射来创建 存储库并将其用作获取数据的示例对象。Spring Data 支持 JPA、MongoDB、Neo4j 和 Redis。​​DataFetcher​​​​QueryByExampleDataFetcher​

如果存储库是,则构建器返回 sor。Spring Data支持这一点 MongoDB,Neo4j,Redis和R2dbc的变体。​​ReactiveQueryByExampleExecutor​​​​DataFetcher<Mono<Account>>​​​​DataFetcher<Flux<Account>>​

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 queries
DataFetcher<AccountProjection> dataFetcher =
QueryByExampleDataFetcher.builder(repository).projectAs(AccountProjection.class).single();

// For multi-result queries
DataFetcher<Iterable<AccountProjection>> 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 记录),因此它们只能在所有情况下构造 必填字段(或列)是数据库查询结果的一部分。


标签:Java,入门,DataFetcher,Spring,builder,GraphQL,注册
From: https://blog.51cto.com/u_15326439/5916430

相关文章

  • SpringBoot文件分片上传,断点续传
    ​ 1 背景用户本地有一份txt或者csv文件,无论是从业务数据库导出、还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工、挖掘和共创应用的时候,首先要将本地文......
  • 爬虫从入门到入狱之入门(2)
    1 css选择器bs4可以通过遍历,搜索,css选择器选择标签frombs4importBeautifulSouphtml_doc="""<html><head><title>TheDormouse'sstory</title></head><body>......
  • 《UnityShader入门精要》 漫反射部分代码及详细注释
    漫反射漫反射计算公式:Cdiffuse=(Clight·Mdiffuse)max(0,n·l)Clight:入射光线的强度和颜色Mdiffuse:材质的漫反射系数物体本色n:法线单位向量l:......
  • SpringMVC文件分片上传,断点续传
    ​ 一、功能性需求与非功能性需求要求操作便利,一次选择多个文件和文件夹进行上传;支持PC端全平台操作系统,Windows,Linux,Mac支持文件和文件夹的批量下载,断点续传。刷......
  • Python全栈工程师之从网页搭建入门到Flask全栈项目实战(4) - Flask模板语法与继承
    1.Flask模板介绍前置:理解渲染机制即上篇笔记中render_template()功能是如何实现的!1)找到html文件地址2)读取html文件中的内容3)替换html中的特殊字符4)将html的内容发送给......
  • Spring-AOP
    代理模式这就是SpringAOP的底层静态代理面向对象的设计原则(7大原则)开闭原则:是总纲,告诉我们要对扩展开放,对修改关闭;通过“抽象约束、封装变化”来实现开闭原......
  • Spring Cloud - Ribbon
    Ribbon相关接口:参考:org.springframework.cloud.netflix.ribbon.RibbonClientConfigurationIClientConfig:Ribbon的客户端配置,默认采用DefaultClientConfigImpl实现。IR......
  • SpringBoot中@Async异步的使用及异步与同步的区别
    简介在开发过程中,异步是提升系统并发能力的一个重要利器。而spring中的@Async异步注解,使我们能够非常方便地实现方法地异步调用。接下来主要结合以下几个问题来讲述j......
  • spring控制事务回滚:TransactionAspectSupport.currentTransactionStatus().setRollbac
    spring事务控制手动回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();1、说明事务是我们开发过程中经常会使用到的,为了在业务执行过程中出......
  • Spring IOC
    SpringIOC介绍介绍引用于https://baijiahao.baidu.com/s?id=1712887849553755889&wfr=spider&for=pcIOC全称是InversionofControl,控制反转。它是一种设计思想,由......