GraphQL 支持

Spring Integration 提供了用于与 GraphQL 协议交互的通道适配器。该实现基于 Spring for GraphQL

你需要将此依赖项添加到你的项目中

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-graphql</artifactId>
    <version>6.4.4</version>
</dependency>
compile "org.springframework.integration:spring-integration-graphql:6.4.4"

GraphQL 出站网关

GraphQlMessageHandlerAbstractReplyProducingMessageHandler 的一个扩展,它代表着一个出站网关契约,用于执行 GraphQL 的 querymutationsubscription 操作并产生其结果。它需要一个 org.springframework.graphql.ExecutionGraphQlService 来执行 operation,该服务可以静态配置,也可以通过 SpEL 表达式针对请求消息进行配置。operationName 是可选的,也可以静态配置或通过 SpEL 表达式配置。variablesExpression 也是可选的,用于参数化操作。locale 是可选的,用于 GraphQL Java 库中的操作执行上下文。executionId 可以通过 SpEL 表达式配置,默认为请求消息的 id 消息头。

如果请求消息的负载是 ExecutionGraphQlRequest 的实例,则在 GraphQlMessageHandler 中不会执行任何设置操作,直接使用此输入作为 ExecutionGraphQlService.execute() 的参数。否则,将使用上面提到的 SpEL 表达式根据请求消息确定 operationoperationNamevariablesexecutionId

GraphQlMessageHandler 是一个响应式流组件,并作为 ExecutionGraphQlService.execute(ExecutionGraphQlRequest) 的结果产生一个 Mono<ExecutionGraphQlResponse> 回复。当输出通道是响应式的 ReactiveStreamsSubscribableChannel 时,框架会订阅此 Mono;当输出通道不是响应式的时,AbstractMessageProducingHandler 会异步订阅。请参阅 ExecutionGraphQlResponse 的文档,了解如何处理 GraphQL 操作结果。

@Bean
GraphQlMessageHandlerSpec graphQlMessageHandlerSpec(ExecutionGraphQlService graphQlService) {
    return GraphQl.gateway(graphQlService)
            .operation("""
                    query HeroNameAndFriends($episode: Episode) {
                      hero(episode: $episode) {
                        name
                        friends {
                          name
                        }
                      }
                    }""")
            .variablesExpression("{episode:'JEDI'}");
}

@Bean
IntegrationFlow graphqlQueryMessageHandlerFlow(GraphQlMessageHandler handler) {
    return IntegrationFlow.from(MessageChannels.flux("inputChannel"))
            .handle(handler)
            .channel(c -> c.flux("resultChannel"))
            .get();
}

@Bean
ExecutionGraphQlService graphQlService(GraphQlSource graphQlSource) {
    return new DefaultExecutionGraphQlService(graphQlSource);
}

@Bean
GraphQlSource graphQlSource(AnnotatedControllerConfigurer annotatedDataFetcherConfigurer) {
    return GraphQlSource.builder()
            .schemaResources(new ClassPathResource("graphql/test-schema.graphqls"))
            .configureRuntimeWiring(annotatedDataFetcherConfigurer)
            .build();
}

@Bean
AnnotatedControllerConfigurer annotatedDataFetcherConfigurer() {
    return new AnnotatedControllerConfigurer();
}

对于订阅操作的结果,需要进行特殊处理。在这种情况下,ExecutionGraphQlResponse.getData() 返回一个 SubscriptionPublisher,需要手动订阅和处理。或者可以通过简单的服务激活器将其扁平映射到 FluxMessageChannel 的回复。

@ServiceActivator(inputChannel = "graphQlResultChannel", outputChannel="graphQlSubscriptionChannel")
public SubscriptionPublisher obtainSubscriptionResult(ExecutionGraphQlResponse graphQlResponse) {
	return graphQlResponse.getData();
}

这种出站网关不仅可以用于通过 HTTP 发送 GraphQL 请求,也可以用于任何上游端点,只要它在消息中产生或携带 GraphQL 操作或其参数。GraphQlMessageHandler 处理的结果可以作为对上游请求的回复产生,或者向下游发送以便在集成流中进一步处理。