JMS 消息监听的正确打开方式SimpleMessageListenerContainer vs DefaultMessageListenerContainer

254 阅读3分钟

大家好,我是G探险者!

本文带你深入理解 Spring 框架中两种最常用的 JMS 消息监听容器:SimpleMessageListenerContainerDefaultMessageListenerContainer,并通过实战告诉你如何优雅、安全、稳定地监听 MQ 消息。


🧠 背景说明

在使用 ActiveMQ、IBM MQ、TongLinkQ 等消息中间件时,Spring 提供了两种强大的消息监听容器:

  • SimpleMessageListenerContainer(简称:SMLC)
  • DefaultMessageListenerContainer(简称:DMLC)

虽然它们都能接收 MQ 消息,但差别极大,使用不当会导致:

  • 监听不到消息
  • 自动重连无效
  • 无法控制线程并发
  • MQ重启后容器崩溃等

📦 一、核心对比一览表

特性SimpleMessageListenerContainerDefaultMessageListenerContainer
线程模型启动时创建固定数量线程支持动态线程调度
并发控制setConcurrentConsumers() 固定setMaxConcurrentConsumers() 支持动态扩容
自动重连❌ 不具备✅ 内建重连机制
Session 事务支持基础支持✅ 更完整的事务控制
配置复杂度简单稍复杂
使用场景简单监听、性能高企业场景、需高可用重连能力

📌 二、典型使用示例

✅ 1. 使用 SimpleMessageListenerContainer

SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setDestinationName("MY.QUEUE");
container.setMessageListener(new MyMessageListener());
container.setConcurrentConsumers(5); // 固定并发线程数
container.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
container.start();

特点:

  • 易用,启动即监听
  • 不支持自动重连,MQ 挂了需要重启容器
  • 不适合生产高可用场景

✅ 2. 使用 DefaultMessageListenerContainer

DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setDestinationName("MY.QUEUE");
container.setMessageListener(new MyMessageListener());
container.setConcurrentConsumers(5);
container.setMaxConcurrentConsumers(10); // 动态扩容
container.setRecoveryInterval(5000); // 重连间隔
container.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
container.afterPropertiesSet(); // ⚠️ 必须调用
container.start();

特点:

  • 支持自动重连:MQ 重启后会自动尝试恢复连接
  • 支持事务:可通过 setSessionTransacted(true) 启用事务
  • 配置项多,但适合生产使用

🚨 三、常见问题与解决

DefaultMessageListenerContainer 无法监听到消息?

✅ 检查是否调用了 afterPropertiesSet(),这是它内部初始化监听线程的必要步骤。

container.afterPropertiesSet(); // 初始化监听线程池
container.start();


❓ MQ 挂了,监听容器崩了?

  • 使用 DefaultMessageListenerContainer
  • 配置自动重连间隔 setRecoveryInterval(5000)
  • 保证底层的连接工厂(如 IBM MQ)也配置了重连参数,如:
connectionFactory.setIntProperty(WMQConstants.WMQ_CLIENT_RECONNECT_OPTIONS,
        WMQConstants.WMQ_CLIENT_RECONNECT);


🔁 四、消息确认与事务模式

JMS 支持的确认模式:

模式含义
AUTO_ACKNOWLEDGE自动确认,消息一旦处理即确认
CLIENT_ACKNOWLEDGE程序手动调用 message.acknowledge()
DUPS_OK_ACKNOWLEDGE延迟确认,允许重复消息
SESSION_TRANSACTED开启事务,使用 commit()/rollback() 控制确认

如何开启事务:

container.setSessionTransacted(true); // 启用事务
container.setSessionAcknowledgeMode(Session.SESSION_TRANSACTED);


🛠 五、实战建议

场景推荐容器
Demo、小规模测试SimpleMessageListenerContainer
生产环境 / MQ 容灾DefaultMessageListenerContainer
多线程并发监听两者皆可,DMLC 支持动态伸缩更优秀
强一致性要求DMLC + JMS事务机制

🧵 六、如何优雅关闭监听容器?

container.stop(); // 停止监听线程

建议结合应用生命周期使用 @PreDestroy 关闭监听,避免服务重启或部署时消息丢失。


✅ 七、结语

Spring JMS 为我们封装了强大的消息监听容器。其中:

  • SimpleMessageListenerContainer 轻量好用
  • DefaultMessageListenerContainer 适合容灾高可用场景

真正的企业级 MQ 应用,应以 容器 + 自动重连 + 可监控 + 容灾保护 为基准线。


下一篇我们将聚焦:

📘 《如何在Spring中实现MQ消息的自动重连:监听与发送双通道策略》