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 出站网关
GraphQlMessageHandler 是 AbstractReplyProducingMessageHandler 的一个扩展,它代表着一个出站网关契约,用于执行 GraphQL 的 query、mutation 或 subscription 操作并产生其结果。它需要一个 org.springframework.graphql.ExecutionGraphQlService 来执行 operation,该服务可以静态配置,也可以通过 SpEL 表达式针对请求消息进行配置。operationName 是可选的,也可以静态配置或通过 SpEL 表达式配置。variablesExpression 也是可选的,用于参数化操作。locale 是可选的,用于 GraphQL Java 库中的操作执行上下文。executionId 可以通过 SpEL 表达式配置,默认为请求消息的 id 消息头。
如果请求消息的负载是 ExecutionGraphQlRequest 的实例,则在 GraphQlMessageHandler 中不会执行任何设置操作,直接使用此输入作为 ExecutionGraphQlService.execute() 的参数。否则,将使用上面提到的 SpEL 表达式根据请求消息确定 operation、operationName、variables 和 executionId。
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 处理的结果可以作为对上游请求的回复产生,或者向下游发送以便在集成流中进一步处理。