我在kafka中使用了一个压缩的主题,该主题在应用程序启动时加载到HashMap中。 然后,我正在听一个普通的消息主题,并使用从压缩的主题构造的HashMap处理它们。
在开始收听其他主题之前,如何确保完全阅读压缩的主题并完全初始化HashMap? (与RestControllers相同)
答案 0 :(得分:1)
实施SmartLifecycle
并将地图加载到start()
中。确保phase
早于需要映射的任何其他对象。
答案 1 :(得分:0)
这是一个老问题,我知道,但我想提供一个更完整的解决方案代码示例,当我自己解决这个问题时,我最终得到了这个解决方案。
这个想法是,就像加里在他自己的答案的评论中提到的那样,在初始化期间使用侦听器不是正确的 - 之后会出现。然而,Garry 的 SmartLifecycle
想法的替代方案是 InitializingBean
,我发现它实现起来并不复杂,因为它只是一种方法:afterPropertiesSet()
:
@Slf4j
@Configuration
@RequiredArgsConstructor
public class MyCacheInitializer implements InitializingBean {
private final ApplicationProperties applicationProperties; // A custom ConfigurationProperties-class
private final KafkaProperties kafkaProperties;
private final ConsumerFactory<String, Bytes> consumerFactory;
private final MyKafkaMessageProcessor messageProcessor;
@Override
public void afterPropertiesSet() {
String topicName = applicationProperties.getKafka().getConsumer().get("my-consumer").getTopic();
Duration pollTimeout = kafkaProperties.getListener().getPollTimeout();
try (Consumer<String, Bytes> consumer = consumerFactory.createConsumer()) {
consumer.subscribe(List.of(topicName));
log.info("Starting to cache the contents of {}", topicName);
ConsumerRecords<String, Bytes> records;
do {
records = consumer.poll(pollTimeout);
records.forEach(messageProcessor::process);
} while (!records.isEmpty());
}
log.info("Completed caching {}", topicName);
}
}
为简洁起见,我使用 Lombok 的 @Slf4j
和 @RequiredArgsConstructor
注释,但这些注释可以轻松替换。 ApplicationProperties
类只是我获取我感兴趣的主题名称的方式。它可以用其他东西替换,但我的实现使用 Lombok 的 @Data
注释,看起来像这样:>
@Data
@Configuration
@ConfigurationProperties(prefix = "app")
public class ApplicationProperties {
private Kafka kafka = new Kafka();
@Data
public static class Kafka {
private Map<String, KafkaConsumer> consumer = new HashMap<>();
}
@Data
public static class KafkaConsumer {
private String topic;
}
}