单个@StreamListener将不同的有效负载类型路由到通用服务类

时间:2019-09-10 12:49:32

标签: java spring-boot spring-kafka spring-cloud-stream

我正在为多个Spring Boot应用程序实现一个公共库,它将为Kafka提供一个简单的接口。我为Kafka集成选择了Spring Cloud Stream。该库必须支持多种不同的有效负载类型,但是我很难理解如何以一种干净通用的方式来完成此工作。

我知道我可以为每种有效负载类型实现多个@StreamListener方法,例如:

    @StreamListener(target = SinkBindings.INPUT, condition = "headers['X-Target-Type'] matches '.*\\.Person'")
    public void listenForMessage(Person payload) {
        // do stuff with payload
    }

但是,该解决方案无法针对许多不同的有效负载类型进行扩展。在理想的情况下,我不希望使用此公共库的应用程序甚至意识到Kafka侦听器方法。取而代之的是,我宁愿提供一个SPI,从而使消费应用程序实现如下所示的接口,并且框架将调用实现中的Spring bean并将正确的有效负载类型传递给它。

public interface MessageHandlingService<T extends BaseClass> {

    void handleMessage(T payload);

}

对于每种有效载荷类型,我希望避免不必实现单独的@StreamListener方法,但是由于Java的类型擦除,这似乎很混乱。我想知道是否存在一种通过单个流侦听器方法将不同的有效负载对象路由到通用服务bean的现实方法?

发生的另一种想法是在上面的接口中添加一个boolean support(Class<?> clazz)方法,这将允许库检查哪个类支持有效负载,但是这似乎有点“ hacky”(???)。

1 个答案:

答案 0 :(得分:1)

传入消息的有效负载将完全转换为预期的类型:否则无法使用@StreamListener。使用@StreamListener的Spring Cloud Stream方法取决于您的方法参数的预期类型。这是用于转换的信号。您无法将有效负载转换为类型,然后尝试仅使用@StreamListener确定要调用的方法。类级别的@KafkaListener和方法上的@KafkaHandler在这里可以为您提供帮助:https://docs.spring.io/spring-kafka/docs/2.3.0.RC1/reference/html/#class-level-kafkalistener

Spring集成流程及其转换功能也可以用于这种逻辑。

在文档中查看有关内容类型协商的更多信息:https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/2.2.1.RELEASE/spring-cloud-stream.html#content-type-management