Skip to content

Spring Integration GraphQL 支持教程

专为初学者设计,通过实用示例逐步掌握 GraphQL 在 Spring Integration 中的应用


一、GraphQL 集成概述

Spring Integration 提供通道适配器实现与 GraphQL 协议的交互,基于 Spring for GraphQL 实现。核心功能:

  • 出站网关:执行 GraphQL 查询/变更/订阅操作
  • 响应式支持:返回 Mono<ExecutionGraphQlResponse>
  • 灵活配置:支持静态或 SpEL 动态表达式

典型应用场景

  • 微服务间 GraphQL 通信
  • 非 HTTP 协议接入 GraphQL(如消息队列)
  • 订阅实时数据流

二、环境配置

1. 添加依赖
kotlin
// build.gradle.kts
dependencies {
    implementation("org.springframework.integration:spring-integration-graphql:6.5.1")
}
xml
<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-graphql</artifactId>
    <version>6.5.1</version>
</dependency>
2. 基础配置
kotlin
@Configuration
class GraphQLConfig {

    // 创建 GraphQL 数据源
    @Bean
    fun graphQlSource(): GraphQlSource = GraphQlSource.builder()
        .schemaResources(ClassPathResource("schema.graphqls"))
        .configureRuntimeWiring(annotatedConfigurer())
        .build()

    // 注册数据获取器
    @Bean
    fun annotatedConfigurer() = AnnotatedControllerConfigurer()

    // 构建 GraphQL 服务
    @Bean
    fun graphQlService(graphQlSource: GraphQlSource): ExecutionGraphQlService =
        DefaultExecutionGraphQlService(graphQlSource)
}

三、GraphQL 出站网关

GraphQlMessageHandler 是核心组件,用于执行 GraphQL 操作并返回响应。

1. 网关配置选项
参数说明
operationGraphQL 操作语句(静态或 SpEL)
operationName操作名称(可选)
variablesExpression参数变量(Map 或 JSON 字符串)
executionId执行 ID(默认使用消息头的 id
2. 创建网关示例
kotlin
@Bean
fun graphQlGateway(graphQlService: ExecutionGraphQlService): GraphQlMessageHandler =
    GraphQl.gateway(graphQlService)
        .operation("""
            query HeroData($episode: Episode!) {
              hero(episode: $episode) {
                name
                friends { name }
              }
            }
        """.trimIndent())
        .variablesExpression("{episode:'JEDI'}")  // pEL 动态传参
        .get()

四、集成流实战

1. 查询/变更操作流
kotlin
@Bean
fun graphqlFlow(handler: GraphQlMessageHandler): IntegrationFlow =
    IntegrationFlow.from(MessageChannels.flux("inputChannel"))
        .handle(handler)
        .channel { c -> c.flux("resultChannel") }
        .get()
2. 订阅操作特殊处理

订阅注意事项

订阅操作返回 SubscriptionPublisher,需手动处理数据流:

kotlin
@ServiceActivator(inputChannel = "resultChannel")
fun handleSubscription(response: ExecutionGraphQlResponse): Flux<String> {
    return response.getData<SubscriptionPublisher>()
        .flatMap { data ->
            // 转换订阅数据流
            Flux.from(data).map { it.toString() }
        }
}

五、动态参数进阶技巧

1. SpEL 动态表达式
kotlin
GraphQl.gateway(graphQlService)
    .operationExpression("headers['operation']")  // 从消息头获取操作
    .variablesExpression("payload.variables")      // 从消息体获取变量
2. 完整请求对象处理

若消息负载是 ExecutionGraphQlRequest 对象,网关直接执行:

kotlin
// 构建自定义请求
val request = ExecutionGraphQlRequest.Builder()
    .query("query { user(id: 1) { name } }")
    .build()

// 发送请求
val message = MessageBuilder.withPayload(request).build()
inputChannel.send(message)

六、常见问题解决方案

CAUTION

问题 1:响应 Mono 未触发处理
原因:输出通道非响应式
解决:使用 ReactiveStreamsSubscribableChannel 或添加订阅逻辑

CAUTION

问题 2:订阅数据无输出
原因:未转换 SubscriptionPublisher
解决:使用 flatMap 转换为 Flux(参考第四节示例)

性能优化建议

复用 ExecutionGraphQlService 实例,避免重复初始化 Schema


七、完整应用示例

点击查看完整配置
kotlin
@Configuration
@EnableIntegration
class AppConfig {

    // GraphQL 基础设施
    @Bean
    fun graphQlSource() = GraphQlSource.builder()
        .schemaResources(ClassPathResource("starwars.graphqls"))
        .build()

    @Bean
    fun graphQlService() = DefaultExecutionGraphQlService(graphQlSource())

    // 网关配置
    @Bean
    fun graphqlGateway() = GraphQl.gateway(graphQlService())
        .operationExpression("payload.query")
        .variablesExpression("payload.variables")
        .get()

    // 集成流
    @Bean
    fun graphqlFlow() = IntegrationFlow
        .from(MessageChannels.direct("requestChannel"))
        .handle(graphqlGateway())
        .transform { response: Mono<ExecutionGraphQlResponse> ->
            response.flatMap { res ->
                if (res.isSubscription) res.getData<SubscriptionPublisher>()
                else Mono.just(res.toSpecification())
            }
        }
        .channel("responseChannel")
        .get()
}

核心优势总结

  • 统一协议:将任意消息源接入 GraphQL
  • 响应式支持:原生集成 Reactor API
  • 动态能力:SpEL 实现运行时参数注入

通过此教程,您已掌握在 Spring Integration 中集成 GraphQL 的核心技能。实际开发时,建议结合 Spring GraphQL 官方文档深化理解。