以编程方式配置侦听器,而不使用注释

时间:2019-08-23 14:26:14

标签: spring-boot spring-kafka

我有read the documentation about receiving messages

  

您可以通过配置MessageListenerContainer并提供消息侦听器或使用@KafkaListener批注来接收消息。

但是我无法完全正常工作。我使用的是Spring Boot 2.1.2,并且可能对Bean造成的危害大于对我的好处,因此可能会使Soup的盐含量过高,所以我想了解它的工作原理,因此我可以检查我偏离了哪里荣耀之路。

如果我正确地理解了文档,那么配置MessageListenerContainer就足够了,例如这个在这里:

@Configuration
public class MyKafkaConfiguration {
  @Bean
  public MessageListenerContainer myVeryOwnListener(ConsumerFactory<String, String> consumerFactory) {
    ContainerProperties cProps = new ContainerProperties(new TopicPartitionInitialOffset("spring-kafka-stackoverflow-questions", /* partition */ 0, /* Offset */ 0L));
    KafkaMessageListenerContainer<String, String> result = new KafkaMessageListenerContainer<>(consumerFactory, cProps);
    result.setupMessageListener(MessageListener<String, String) System.out::println);
    return result;
  }
}

这将毫无例外地启动,但实际上似乎并未监听代理上的任何消息。 从我从带注释的通常流程中获得的信息来看,需要有人以KafkaListenerEndpointKafkaListenerEndpointRegistry的形式注册侦听器。

KafkaListenerAnnotationBeanPostPorcessor会自动对@KafkaListener注释的所有方法执行此操作,但是在我想采用路径的情况下,这应该如何工作

  

通过配置MessageListenerContainer并提供消息侦听器

代替

  

使用@KafkaListener批注

我不太明白。此外,KafkaAutoConfiguration中没有任何方法(Spring Boot提供),例如使用List<MessageListenerContainer>并自动将它们全部注册到注册表中,因此这并不奇怪。

但是,正如文档所建议的,它首先应该如何工作?我误会了那部分吗? 有人可以启发我吗?

2 个答案:

答案 0 :(得分:2)

该文档的下一部分说:

  

使用消息侦听器容器时,必须提供一个侦听器以接收数据。当前有八个支持的消息侦听器接口。以下清单显示了这些接口

然后有一个节Using KafkaMessageListenerContainer

  

要将MessageListener分配给容器,可以在创建容器时使用ContainerProps.setMessageListener方法。以下示例显示了如何执行此操作:

ContainerProperties containerProps = new ContainerProperties("topic1", "topic2");
containerProps.setMessageListener(new MessageListener<Integer, String>() {
    ...
});
DefaultKafkaConsumerFactory<Integer, String> cf =
                        new DefaultKafkaConsumerFactory<Integer, String>(consumerProps());
KafkaMessageListenerContainer<Integer, String> container =
                        new KafkaMessageListenerContainer<>(cf, containerProps);
return container;

该参考文献的开头有一个完整的示例:https://docs.spring.io/spring-kafka/docs/2.2.8.RELEASE/reference/html/#a-very-very-quick-example

@Test
public void testAutoCommit() throws Exception {
    logger.info("Start auto");
    ContainerProperties containerProps = new ContainerProperties("topic1", "topic2");
    final CountDownLatch latch = new CountDownLatch(4);
    containerProps.setMessageListener(new MessageListener<Integer, String>() {

        @Override
        public void onMessage(ConsumerRecord<Integer, String> message) {
            logger.info("received: " + message);
            latch.countDown();
        }

    });
    KafkaMessageListenerContainer<Integer, String> container = createContainer(containerProps);
    container.setBeanName("testAuto");
    container.start();
    Thread.sleep(1000); // wait a bit for the container to start
    KafkaTemplate<Integer, String> template = createTemplate();
    template.setDefaultTopic(topic1);
    template.sendDefault(0, "foo");
    template.sendDefault(2, "bar");
    template.sendDefault(0, "baz");
    template.sendDefault(2, "qux");
    template.flush();
    assertTrue(latch.await(60, TimeUnit.SECONDS));
    container.stop();
    logger.info("Stop auto");

}

答案 1 :(得分:1)

我刚刚将您的bean复制到了新的启动应用程序中,并且工作正常。

端点注册表仅适用于@KafkaListener容器,因为它们没有在应用程序上下文中注册为bean(注册表是bean)。


@SpringBootApplication
public class So57628247Application {

    private static final int MessageListener = 0;

    public static void main(String[] args) {
        SpringApplication.run(So57628247Application.class, args);
    }

    @Bean
    public MessageListenerContainer myVeryOwnListener(ConsumerFactory<String, String> consumerFactory) {
        ContainerProperties cProps = new ContainerProperties(new TopicPartitionInitialOffset(
                "spring-kafka-stackoverflow-questions", /* partition */ 0, /* Offset */ 0L));
        KafkaMessageListenerContainer<String, String> result = new KafkaMessageListenerContainer<>(consumerFactory,
                cProps);
        result.setupMessageListener((MessageListener<String, String>) System.out::println);
        return result;
    }

    @Bean
    public NewTopic topic() {
        return new NewTopic("spring-kafka-stackoverflow-questions", 1, (short) 1);
    }


    @Bean
    public ApplicationRunner runner(KafkaTemplate<String, String> template) {
        return args -> {
            template.send("spring-kafka-stackoverflow-questions", "foo");
        };
    }

}

  

ConsumerRecord(主题= spring-kafka-stackoverflow-questions,分区= 0,偏移量= 0,CreateTime = 1566573407373,序列化密钥大小= -1,序列化值大小= 3,标头= RecordHeaders(标头= [],isReadOnly = false),键= null,值= foo)