如何在spring boot应用程序启动期间创建许多kafka主题?

如何在spring boot应用程序启动期间创建许多kafka主题?,spring,spring-boot,apache-kafka,spring-kafka,spring-config,Spring,Spring Boot,Apache Kafka,Spring Kafka,Spring Config,我有以下配置: @Configuration public class KafkaTopicConfig { private final TopicProperties topics; public KafkaTopicConfig(TopicProperties topics) { this.topics = topics; } @Bean public NewTopic newTopicImportCharge() {

我有以下配置:

@Configuration
public class KafkaTopicConfig {

    private final TopicProperties topics;

    public KafkaTopicConfig(TopicProperties topics) {
        this.topics = topics;
    }

    @Bean
    public NewTopic newTopicImportCharge() {
        TopicProperties.Topic topic = topics.getTopicNameByType(MessageType.IMPORT_CHARGES.name());
        return new NewTopic(topic.getTopicName(), topic.getNumPartitions(), topic.getReplicationFactor());
    }

    @Bean
    public NewTopic newTopicImportPayment() {
        TopicProperties.Topic topic = topics.getTopicNameByType(MessageType.IMPORT_PAYMENTS.name());
        return new NewTopic(topic.getTopicName(), topic.getNumPartitions(), topic.getReplicationFactor());
    }

    @Bean
    public NewTopic newTopicImportCatalog() {
        TopicProperties.Topic topic = topics.getTopicNameByType(MessageType.IMPORT_CATALOGS.name());
        return new NewTopic(topic.getTopicName(), topic.getNumPartitions(), topic.getReplicationFactor());
    }
}

我可以在
TopicProperties
中添加10个不同的主题。我不想手动创建每个类似的bean。在春季卡夫卡中是否存在创建所有主题的方法,或者仅春季

直接使用管理客户端;您可以从Boot的
KafkaAdmin
获取预构建属性映射

@springboot应用程序
公共类SO55336461应用程序{
公共静态void main(字符串[]args){
SpringApplication.run(So55336461Application.class,args);
}
@豆子
公共应用程序运行程序运行程序(KafkaAdmin KafkaAdmin){
返回参数->{
AdminClient admin=AdminClient.create(kafkaAdmin.getConfig());
列表主题=新建ArrayList();
//构建列表
admin.createTopics(topics.all().get();
};
}
}
编辑

为了检查它们是否已经存在,或者是否需要增加分区,
KafkaAdmin
具有以下逻辑

private void addTopicsIfNeeded(AdminClient adminClient, Collection<NewTopic> topics) {
    if (topics.size() > 0) {
        Map<String, NewTopic> topicNameToTopic = new HashMap<>();
        topics.forEach(t -> topicNameToTopic.compute(t.name(), (k, v) -> t));
        DescribeTopicsResult topicInfo = adminClient
                .describeTopics(topics.stream()
                        .map(NewTopic::name)
                        .collect(Collectors.toList()));
        List<NewTopic> topicsToAdd = new ArrayList<>();
        Map<String, NewPartitions> topicsToModify = checkPartitions(topicNameToTopic, topicInfo, topicsToAdd);
        if (topicsToAdd.size() > 0) {
            addTopics(adminClient, topicsToAdd);
        }
        if (topicsToModify.size() > 0) {
            modifyTopics(adminClient, topicsToModify);
        }
    }
}

private Map<String, NewPartitions> checkPartitions(Map<String, NewTopic> topicNameToTopic,
        DescribeTopicsResult topicInfo, List<NewTopic> topicsToAdd) {

    Map<String, NewPartitions> topicsToModify = new HashMap<>();
    topicInfo.values().forEach((n, f) -> {
        NewTopic topic = topicNameToTopic.get(n);
        try {
            TopicDescription topicDescription = f.get(this.operationTimeout, TimeUnit.SECONDS);
            if (topic.numPartitions() < topicDescription.partitions().size()) {
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info(String.format(
                        "Topic '%s' exists but has a different partition count: %d not %d", n,
                        topicDescription.partitions().size(), topic.numPartitions()));
                }
            }
            else if (topic.numPartitions() > topicDescription.partitions().size()) {
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info(String.format(
                        "Topic '%s' exists but has a different partition count: %d not %d, increasing "
                        + "if the broker supports it", n,
                        topicDescription.partitions().size(), topic.numPartitions()));
                }
                topicsToModify.put(n, NewPartitions.increaseTo(topic.numPartitions()));
            }
        }
        catch (@SuppressWarnings("unused") InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        catch (TimeoutException e) {
            throw new KafkaException("Timed out waiting to get existing topics", e);
        }
        catch (@SuppressWarnings("unused") ExecutionException e) {
            topicsToAdd.add(topic);
        }
    });
    return topicsToModify;
}
private void addTopicsIfNeeded(AdminClient AdminClient,集合主题){
如果(topics.size()>0){
Map topicNameToTopic=新HashMap();
topic.forEach(t->topicnametopic.compute(t.name(),(k,v)->t));
descripbetopicsResult topicInfo=adminClient
.descripbetopics(topics.stream()
.map(NewTopic::name)
.collect(Collectors.toList());
List topicsToAdd=新建ArrayList();
Map topicsToModify=检查分区(topicNameToTopic、topicInfo、topicsToAdd);
如果(topicsToAdd.size()>0){
添加主题(adminClient、topicsToAdd);
}
如果(topicsToModify.size()>0){
修改主题(adminClient、topicsToModify);
}
}
}
私有映射检查分区(映射topicNameToTopic,
描述TopicsResult主题信息,列出要添加的主题){
Map topicsToModify=new HashMap();
topicInfo.values().forEach((n,f)->{
NewTopic=topicNameToTopic.get(n);
试一试{
TopicDescription TopicDescription=f.get(this.operationTimeout,TimeUnit.SECONDS);
if(topic.numPartitions()topicDescription.partitions().size()){
如果(LOGGER.IsInfo已启用()){
LOGGER.info(String.format(
主题“%s”存在,但分区计数不同:%d而不是%d,正在增加
+“如果经纪人支持”,n,
topicDescription.partitions().size(),topic.numPartitions());
}
topicsToModify.put(n,NewPartitions.increaseTo(topic.numPartitions());
}
}
捕获(@SuppressWarnings(“未使用”)中断异常e){
Thread.currentThread().interrupt();
}
捕获(超时异常e){
抛出新的KafkaException(“等待获取现有主题超时”,e);
}
捕获(@SuppressWarnings(“未使用”)执行异常){
主题添加(主题);
}
});
回归主题;
}

回答很好,但当我第二次启动应用程序时,我收到一个错误:
由以下原因引起:java.util.concurrent.ExecutionException:org.apache.kafka.common.errors.topicexist异常:主题“我的主题”已经存在。
所以,首先检查它们是否存在。我添加了管理员用来做这件事的代码。