GraphQL Support

Spring Integration 提供了信道适配器来与 GraphQL 协议进行交互。该实现基于 Spring for GraphQL

Spring Integration provides channel adapters for interaction with GraphQL protocol. The implementation is based on the Spring for GraphQL.

你需要将此依赖项包含在你的项目中:

You need to include this dependency into your project:

  • Maven

  • Gradle

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

GraphQL Outbound Gateway

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

The GraphQlMessageHandler is an AbstractReplyProducingMessageHandler extension representing an outbound gateway contract to perform GraphQL query, mutation or subscription operation and produce their result. It requires a org.springframework.graphql.ExecutionGraphQlService for execution of an operation, which can be configured statically or via SpEL expression against a request message. The operationName is optional and also can be configured statically or via SpEL expression. The variablesExpression is also optional and used for parametrized operations. The locale is optional and used for operation execution context in the GraphQL Java library. The executionId can be configured via SpEL expression and defaults to id header of the request message.

如果请求消息有效负载是 ExecutionGraphQlRequest 的实例,那么在 GraphQlMessageHandler 中不会执行任何设置操作,并且该输入将按原样用于 ExecutionGraphQlService.execute()。否则,将使用上面提到的 SpEL 表达式针对请求消息确定 operationoperationNamevariablesexecutionId

If the payload of the request message is an instance of ExecutionGraphQlRequest, then there’s no any setup actions are performed in the GraphQlMessageHandler and such an input is used as is for the ExecutionGraphQlService.execute(). Otherwise, the operation, operationName, variables and executionId are determined against request message using SpEL expressions mentioned above.

GraphQlMessageHandler 是一个响应式流组件,并将 ExecutionGraphQlService.execute(ExecutionGraphQlRequest) 的结果作为 Mono<ExecutionGraphQlResponse> 回复生成。该 MonoReactiveStreamsSubscribableChannel 输出通道中的框架或在输出通道非响应式时异步地在 AbstractMessageProducingHandler 中订阅。请参阅 ExecutionGraphQlResponse 文档,了解如何处理 GraphQL 操作结果。

The GraphQlMessageHandler is a reactive streams component and produces a Mono<ExecutionGraphQlResponse> reply as a result of the ExecutionGraphQlService.execute(ExecutionGraphQlRequest). Such a Mono is subscribed by the framework in the ReactiveStreamsSubscribableChannel output channel or in the AbstractMessageProducingHandler asynchronously when the output channel is not reactive. See documentation for the ExecutionGraphQlResponse how to process the GraphQL operation result.

@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 的回复:

The special treatment should be applied for the result of a subscription operation. In this case the ExecutionGraphQlResponse.getData() returns a SubscriptionPublisher which has to subscribed and processed manually. Or it can be flat-mapped via plain service activator to the reply for the FluxMessageChannel:

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

不仅可以通过 HTTP 进行 GraphQL 请求,还可以从任何生成或携带 GraphQL 操作或其消息中参数的上游端点使用此出站网关。GraphQlMessageHandler 处理的结果可作为对上游请求的回复生成,或向下发送以在集成流中进一步处理。

Such an outbound gateway can be used not only for GraphQL request via HTTP, but from any upstream endpoint which produces or carries a GraphQL operation or its arguments in the message. The result of the GraphQlMessageHandler handling can be produced as a reply to the upstream request or sent downstream for further processing in the integration flow.