kafka动态监听主题

简单版本

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
import org.springframework.kafka.listener.ContainerProperties;
import org.springframework.kafka.listener.MessageListener;
import org.springframework.stereotype.Service;

@Service
public class DynamicKafkaListenerService {

    @Autowired
    private ConsumerFactory<String, String> consumerFactory;

    public void registerListener(String topic) {
        ContainerProperties containerProperties = new ContainerProperties(topic);
        containerProperties.setMessageListener((MessageListener<String, String>) record -> {
            System.out.println(Thread.currentThread().getName() + " 主题 " + topic + " 收到消息: " + record.value());
        });
        ConcurrentMessageListenerContainer<String, String> container = new ConcurrentMessageListenerContainer<>(consumerFactory, containerProperties);
        container.setBeanName(topic + "-listener");
        container.start();
    }
}

手动ack版本

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.listener.AcknowledgingMessageListener;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
import org.springframework.kafka.listener.ContainerProperties;
import org.springframework.stereotype.Service;

@Service
public class DynamicKafkaListenerService {

    @Autowired
    private ConsumerFactory<String, String> consumerFactory;

    public void registerListener(String topic) {
        ContainerProperties containerProperties = new ContainerProperties(topic);
        // 设置消息监听器为 AcknowledgingMessageListener
        containerProperties.setMessageListener((AcknowledgingMessageListener<String, String>) (record, ack) -> {
            try {
                System.out.println(Thread.currentThread().getName() + " 主题 " + topic + " 收到消息: " + record.value());
                // 模拟消息处理逻辑
                // 处理完成后手动确认消息
                if (ack != null) {
                    ack.acknowledge();
                }
            } catch (Exception e) {
                // 处理异常情况,例如记录日志或重试等
                System.err.println("消息处理失败: " + e.getMessage());
            }
        });
        // 设置手动确认模式
        containerProperties.setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
        ConcurrentMessageListenerContainer<String, String> container = new ConcurrentMessageListenerContainer<>(consumerFactory, containerProperties);
        container.setBeanName(topic + "-listener");
        container.start();
    }
}

批量处理版本

java 复制代码
    @Autowired
    private ConsumerFactory<String, String> consumerFactory;

    public void registerListener(String topic) {
        ContainerProperties containerProperties = new ContainerProperties(topic);
        // 设置手动确认模式
        containerProperties.setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
        // 设置批量消息监听器
        containerProperties.setMessageListener((BatchAcknowledgingMessageListener<String, String>) (records, ack) -> {
            try {
                for (ConsumerRecord<String, String> record : records) {
                    System.out.println(Thread.currentThread().getName() + " 主题 " + topic + " 收到消息: " + record.value());
                }
                // 模拟消息处理逻辑
                // 处理完成后手动批量确认消息
                ack.acknowledge();
            } catch (Exception e) {
                // 处理异常情况,例如记录日志或重试等
                System.err.println("消息处理失败: " + e.getMessage());
            }
        });
        ConcurrentMessageListenerContainer<String, String> container = new ConcurrentMessageListenerContainer<>(consumerFactory, containerProperties);
        container.setBeanName(topic + "-listener");
        container.start();
    }

可关闭版本

java 复制代码
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.listener.BatchAcknowledgingMessageListener;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
import org.springframework.kafka.listener.ContainerProperties;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class DynamicKafkaListenerService {


    @Autowired
    private ConsumerFactory<String, String> consumerFactory;

    // 用于保存每个主题对应的监听器容器
    private final Map<String, ConcurrentMessageListenerContainer<String, String>> containerMap = new HashMap<>();

    /**
     * 开启一个监听
     */
    public void registerListener(String topic) {
        ContainerProperties containerProperties = new ContainerProperties(topic);
        // 设置手动确认模式
        containerProperties.setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
        // 设置批量消息监听器
        containerProperties.setMessageListener((BatchAcknowledgingMessageListener<String, String>) (records, ack) -> {
            try {
                for (ConsumerRecord<String, String> record : records) {
                    System.out.println(Thread.currentThread().getName() + " 主题 " + topic + " 收到消息: " + record.value());
                }
                // 模拟消息处理逻辑
                // 处理完成后手动批量确认消息
                ack.acknowledge();
            } catch (Exception e) {
                // 处理异常情况,例如记录日志或重试等
                System.err.println("消息处理失败: " + e.getMessage());
            }
        });
        ConcurrentMessageListenerContainer<String, String> container = new ConcurrentMessageListenerContainer<>(consumerFactory, containerProperties);
        container.setBeanName(topic + "-listener");
        container.start();
        // 将监听器容器保存到 map 中
        containerMap.put(topic, container);
    }

    /**
     * 关闭一个监听
     */
    public void stopListener(String topic) {
        ConcurrentMessageListenerContainer<String, String> container = containerMap.get(topic);
        if (container != null && container.isRunning()) {
            container.stop();
            // 从 map 中移除已停止的监听器容器
            containerMap.remove(topic);
        }
    }
}

调用添加监听

java 复制代码
    /**
     * 配置详情
     */
    @GetMapping("/getModelZdyConfInfo")
    public String getModelZdyConfInfo(String topic) {
        dynamicKafkaListenerService.registerListener(topic);
        return "添加" + topic + "监听成功";
    }
相关推荐
罗四强6 分钟前
第10篇:打包上架:签名、打包 HAP、发布到华为应用市场
分布式·操作系统·harmonyos·arkts·鸿蒙系统
秋饼15 分钟前
Redis 全面解析:从数据结构到主从/哨兵/集群、分布式锁与面试高频考点,代码到原理一次讲透
数据库·redis·分布式·面试·后端开发
二月夜16 分钟前
Redis 高频面试题全解:缓存三大问题、大 key 治理与分布式锁之争(2026 招聘 JD 真题复盘)
redis·分布式·后端·缓存
后台模板学习33 分钟前
Kafka 与 RabbitMQ 在用户认证与权限管理场景
kafka·rabbitmq·linq
樱花落木兰34 分钟前
Redis 消息队列的可靠性演进:从 List、Pub/Sub 到 Stream 消费者组,以及 8.x 版本改变了什么
java·开发语言·经验分享·redis·分布式·python·软件工程
真上帝的左手3 小时前
12. 消息队列-Kafka进阶
分布式·中间件·kafka
Thanks_ks21 小时前
Cookie 和 Session 到底是什么关系——登录态是怎么维持的
分布式·http·jwt·cookie·session·后端开发·登录态
千里达景区票务系统1 天前
消息队列选型对比:RabbitMQ vs RocketMQ vs Kafka
kafka·消息队列·rabbitmq·rocketmq
Sayai1 天前
Kafka 跨数据中心日志同步实战:MirrorMaker 2 选型对比 + Flink 中继任务落地(双中心互备与消费者组隔离避坑)
大数据·运维·分布式·flink·kafka·消息队列·高可用
jianjinwssy1 天前
从零设计一个 Agent 安全沙箱:Docker 隔离、三级风控与 Kafka 审计
人工智能·docker·kafka