Java ActiveMQ 实战指南:从 JMS 队列、主题到 Spring Boot 消息处理
简介
ActiveMQ 是 Apache 提供的消息中间件。
它在 Java 生态里很常见,尤其是传统企业系统、老项目改造、JMS 规范相关系统中出现得比较多。
简单理解:
生产者 | v ActiveMQ Broker | v 消费者
ActiveMQ 最常见的使用方式是 JMS。
JMS 全称是 Java Message Service,它是一套 Java 消息服务 API 规范。
ActiveMQ 和 JMS 的关系可以类比成:
JMS 是规范 ActiveMQ 是实现
一句话概括:
ActiveMQ 是 Java 生态里经典的 JMS 消息中间件,适合异步处理、系统解耦、任务队列和发布订阅场景。
ActiveMQ 解决什么问题
一个业务动作经常会带出很多后续动作。
比如订单创建成功后:
扣库存 发短信 发邮件 写日志 生成物流任务 同步积分
如果全部同步执行,接口会变慢。
如果短信服务异常,订单接口也可能被影响。
使用 ActiveMQ 后,可以拆成:
订单服务 | v 发送订单消息 | v ActiveMQ | +--> 库存服务消费消息 +--> 短信服务消费消息 +--> 邮件服务消费消息 +--> 日志服务消费消息
常见作用:
- 异步处理
- 系统解耦
- 削峰填谷
- 任务分发
- 发布订阅
- 消息重试和失败兜底
ActiveMQ Classic 和 Artemis
ActiveMQ 需要先区分两条线:
| 名称 | 说明 |
|---|---|
ActiveMQ Classic |
传统 ActiveMQ 5.x / 6.x 线,老项目和 JMS 系统常见 |
ActiveMQ Artemis |
新一代消息 Broker,性能和架构更现代 |
简单理解:
ActiveMQ Classic:经典 JMS Broker ActiveMQ Artemis:新一代多协议、高性能 Broker
如果是维护老系统,经常会遇到 ActiveMQ Classic。
如果是新系统选型,并且明确要用 Apache ActiveMQ 体系,Artemis 更值得优先评估。
本文示例以 ActiveMQ Classic + Spring Boot JMS 为主,因为它更贴近日常 Java 老系统和企业项目集成场景。
ActiveMQ 和 RabbitMQ 的区别
| 对比项 | ActiveMQ | RabbitMQ |
|---|---|---|
| 常见协议 | JMS、OpenWire、STOMP、AMQP、MQTT | AMQP 为主,也支持多协议 |
| Java 规范关系 | JMS 体系很强 | 不以 JMS 为核心 |
| 核心模型 | Queue / Topic | Exchange / Queue / Binding |
| 路由能力 | JMS 模型更直接 | Exchange 路由更灵活 |
| 常见场景 | 传统企业系统、JMS 项目 | 微服务消息、灵活路由、事件分发 |
ActiveMQ 更像:
Queue / Topic 模型清晰,适合 JMS 项目。
RabbitMQ 更像:
Exchange + Routing Key 更灵活,适合复杂路由。
JMS 核心概念
| 概念 | 说明 |
|---|---|
ConnectionFactory |
连接工厂 |
Connection |
客户端到 Broker 的连接 |
Session |
会话,负责生产、消费、确认、事务 |
Destination |
目的地,Queue 或 Topic |
Queue |
点对点队列 |
Topic |
发布订阅主题 |
MessageProducer |
消息生产者 |
MessageConsumer |
消息消费者 |
Message |
消息对象 |
整体流程:
ConnectionFactory | v Connection | v Session | +--> MessageProducer -> Destination | +--> MessageConsumer <- Destination
Queue 点对点模式
Queue 是点对点模式。
特点:
一条消息只会被一个消费者处理。
示例:
order.queue | +--> consumer-1 +--> consumer-2
如果 order.queue 有 10 条消息,两个消费者会竞争消费。
每条消息最终只会被其中一个消费者处理。
适合:
- 订单处理
- 短信发送
- 邮件发送
- 报表生成
- 后台任务
Topic 发布订阅模式
Topic 是发布订阅模式。
特点:
一条消息可以被多个订阅者收到。
示例:
order.topic | +--> sms-consumer +--> email-consumer +--> log-consumer
订单支付成功消息发送到 order.topic 后,短信、邮件、日志服务都能收到。
适合:
- 业务事件广播
- 通知消息
- 日志订阅
- 缓存刷新
Topic 持久订阅和非持久订阅
Topic 需要注意订阅方式。
| 类型 | 离线期间消息是否保留 | 说明 |
|---|---|---|
| 非持久订阅 | 不保留 | 消费者在线时才能收到 |
| 持久订阅 | 保留 | 消费者离线后再上线也能收到 |
非持久订阅适合临时通知。
持久订阅适合关键业务事件。
持久订阅通常需要设置唯一的 clientId 和订阅名。
Docker 启动 ActiveMQ Classic
本地学习可以使用 Docker。
不同镜像维护方式不同,实际项目以团队镜像仓库或官方发布包为准。
示例:
docker run -d \ --name activemq-classic \ -p 61616:61616 \ -p 8161:8161 \ apache/activemq-classic:latest
端口说明:
| 端口 | 作用 |
|---|---|
61616 |
JMS / OpenWire 连接端口 |
8161 |
Web 管理控制台 |
管理后台:
http://localhost:8161/admin
常见默认账号:
admin / admin
如果镜像没有提供默认账号,需要查看镜像说明或自定义配置。
原生 JMS 依赖
Spring Boot 3 使用 jakarta.jms 包名。
如果使用 ActiveMQ Classic 6 或 Jakarta 体系,可以选择 Jakarta 版本客户端。
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-client-jakarta</artifactId> <version>${activemq.version}</version> </dependency>
如果是老项目,可能仍然使用 javax.jms 和 ActiveMQ 5.x 客户端。
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-client</artifactId> <version>${activemq.version}</version> </dependency>
包名差异:
老项目:javax.jms.* 新项目:jakarta.jms.*
原生 JMS:发送 Queue 消息
package com.example.activemq.raw; import jakarta.jms.Connection; import jakarta.jms.ConnectionFactory; import jakarta.jms.DeliveryMode; import jakarta.jms.Destination; import jakarta.jms.MessageProducer; import jakarta.jms.Session; import jakarta.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class RawQueueProducer { private static final String BROKER_URL = "tcp://localhost:61616"; private static final String QUEUE_NAME = "order.queue"; public static void main(String[] args) throws Exception { ConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL); try (Connection connection = factory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { Destination destination = session.createQueue(QUEUE_NAME); MessageProducer producer = session.createProducer(destination); producer.setDeliveryMode(DeliveryMode.PERSISTENT); TextMessage message = session.createTextMessage("订单创建成功"); message.setStringProperty("bizType", "order"); message.setStringProperty("messageId", "msg-1001"); producer.send(message); System.out.println("消息已发送:" + message.getText()); } } }
说明:
Session.AUTO_ACKNOWLEDGE:自动确认 DeliveryMode.PERSISTENT:持久化消息 createQueue:创建 Queue 目的地
原生 JMS:消费 Queue 消息
package com.example.activemq.raw; import jakarta.jms.Connection; import jakarta.jms.ConnectionFactory; import jakarta.jms.MessageConsumer; import jakarta.jms.Session; import jakarta.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class RawQueueConsumer { private static final String BROKER_URL = "tcp://localhost:61616"; private static final String QUEUE_NAME = "order.queue"; public static void main(String[] args) throws Exception { ConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL); Connection connection = factory.createConnection(); Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(session.createQueue(QUEUE_NAME)); connection.start(); consumer.setMessageListener(message -> { try { if (message instanceof TextMessage textMessage) { System.out.println("收到消息:" + textMessage.getText()); } message.acknowledge(); } catch (Exception e) { throw new RuntimeException(e); } }); System.out.println("消费者已启动"); Thread.currentThread().join(); } }
CLIENT_ACKNOWLEDGE 表示客户端手动确认。
注意:
JMS 的 acknowledge() 可能确认当前 Session 中已消费的一批消息。
如果需要更强的边界控制,可以考虑事务会话。
JMS 确认模式
JMS 常见确认模式:
| 模式 | 说明 |
|---|---|
AUTO_ACKNOWLEDGE |
监听器正常返回后自动确认 |
CLIENT_ACKNOWLEDGE |
客户端调用 acknowledge() 确认 |
DUPS_OK_ACKNOWLEDGE |
允许延迟确认,可能出现重复 |
SESSION_TRANSACTED |
使用事务提交或回滚 |
AUTO_ACKNOWLEDGE 使用简单。
关键业务更常见的是事务或手动确认。
JMS 事务
创建事务会话:
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
处理成功:
session.commit();
处理失败:
session.rollback();
示例:
MessageConsumer consumer = session.createConsumer(session.createQueue("order.queue")); TextMessage message = (TextMessage) consumer.receive(); try { System.out.println("处理消息:" + message.getText()); // 执行业务逻辑 session.commit(); } catch (Exception e) { session.rollback(); }
事务回滚后,消息会重新投递。
Spring Boot 依赖
Spring Boot 集成 ActiveMQ Classic:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency>
如果选择 Artemis:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-artemis</artifactId> </dependency>
Classic 和 Artemis 不建议在同一个应用里混用。
application.yml
ActiveMQ Classic 示例:
spring: activemq: broker-url: tcp://localhost:61616 user: admin password: admin jms: listener: acknowledge-mode: auto
如果需要连接池,可以配置连接池依赖和对应参数。
不同 Spring Boot 版本对连接池自动配置细节略有差异,实际项目以当前版本文档为准。
开启 JMS 注解
使用 @JmsListener 需要开启 JMS 注解支持。
package com.example.activemq.config; import org.springframework.context.annotation.Configuration; import org.springframework.jms.annotation.EnableJms; @Configuration @EnableJms public class JmsConfig { }
消息对象
package com.example.activemq.order; import java.math.BigDecimal; import java.time.LocalDateTime; public record OrderCreatedMessage( Long orderId, String orderNo, Long userId, BigDecimal amount, LocalDateTime createdAt ) { }
JSON 消息转换器
业务系统里更常用 JSON,而不是 Java 原生对象序列化。
package com.example.activemq.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.converter.MessageType; @Configuration public class JmsMessageConfig { @Bean public MessageConverter jacksonJmsMessageConverter() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); converter.setTargetType(MessageType.TEXT); converter.setTypeIdPropertyName("_type"); return converter; } }
Queue 实战:订单消息
常量:
package com.example.activemq.config; public class ActiveMqDestinations { public static final String ORDER_QUEUE = "order.queue"; public static final String NOTICE_TOPIC = "notice.topic"; private ActiveMqDestinations() { } }
生产者:
package com.example.activemq.order; import com.example.activemq.config.ActiveMqDestinations; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Service; @Service public class OrderMessageProducer { private final JmsTemplate jmsTemplate; public OrderMessageProducer(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendOrderCreated(OrderCreatedMessage message) { jmsTemplate.convertAndSend(ActiveMqDestinations.ORDER_QUEUE, message); } }
消费者:
package com.example.activemq.order; import com.example.activemq.config.ActiveMqDestinations; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class OrderMessageConsumer { @JmsListener(destination = ActiveMqDestinations.ORDER_QUEUE) public void handle(OrderCreatedMessage message) { System.out.println("收到订单消息:" + message); // 执行业务逻辑:扣库存、发通知、写日志等 } }
Controller:
package com.example.activemq.order; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; import java.time.LocalDateTime; @RestController @RequestMapping("/api/orders") public class OrderController { private final OrderMessageProducer producer; public OrderController(OrderMessageProducer producer) { this.producer = producer; } @PostMapping public String createOrder() { OrderCreatedMessage message = new OrderCreatedMessage( 1001L, "O202606300001", 2001L, new BigDecimal("99.80"), LocalDateTime.now() ); producer.sendOrderCreated(message); return "订单消息已发送"; } }
访问:
POST http://localhost:8080/api/orders
同时支持 Queue 和 Topic
JmsTemplate 有一个关键属性:
pubSubDomain
含义:
false:Queue 模式 true:Topic 模式
如果一个项目同时使用 Queue 和 Topic,可以分别创建两个模板。
package com.example.activemq.config; import jakarta.jms.ConnectionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.core.JmsTemplate; @Configuration public class JmsTemplateConfig { @Bean public JmsTemplate queueJmsTemplate(ConnectionFactory connectionFactory) { JmsTemplate template = new JmsTemplate(connectionFactory); template.setPubSubDomain(false); return template; } @Bean public JmsTemplate topicJmsTemplate(ConnectionFactory connectionFactory) { JmsTemplate template = new JmsTemplate(connectionFactory); template.setPubSubDomain(true); return template; } @Bean public DefaultJmsListenerContainerFactory topicListenerContainerFactory( ConnectionFactory connectionFactory ) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setPubSubDomain(true); return factory; } }
Topic 实战:广播通知
生产者:
package com.example.activemq.notice; import com.example.activemq.config.ActiveMqDestinations; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Service; @Service public class NoticeProducer { private final JmsTemplate topicJmsTemplate; public NoticeProducer(@Qualifier("topicJmsTemplate") JmsTemplate topicJmsTemplate) { this.topicJmsTemplate = topicJmsTemplate; } public void publish(String content) { topicJmsTemplate.convertAndSend(ActiveMqDestinations.NOTICE_TOPIC, content); } }
短信消费者:
package com.example.activemq.notice; import com.example.activemq.config.ActiveMqDestinations; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class SmsNoticeConsumer { @JmsListener( destination = ActiveMqDestinations.NOTICE_TOPIC, containerFactory = "topicListenerContainerFactory" ) public void handle(String message) { System.out.println("短信服务收到通知:" + message); } }
邮件消费者:
package com.example.activemq.notice; import com.example.activemq.config.ActiveMqDestinations; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class EmailNoticeConsumer { @JmsListener( destination = ActiveMqDestinations.NOTICE_TOPIC, containerFactory = "topicListenerContainerFactory" ) public void handle(String message) { System.out.println("邮件服务收到通知:" + message); } }
一条 Topic 消息会被两个消费者都收到。
Topic 持久订阅 Demo
非持久订阅只接收在线期间的 Topic 消息。
持久订阅需要设置 clientId 和订阅名。
@Bean public DefaultJmsListenerContainerFactory durableTopicListenerContainerFactory( ConnectionFactory connectionFactory ) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setPubSubDomain(true); factory.setSubscriptionDurable(true); factory.setClientId("notice-service-01"); return factory; }
监听:
@JmsListener( destination = ActiveMqDestinations.NOTICE_TOPIC, subscription = "notice-service-subscription", containerFactory = "durableTopicListenerContainerFactory" ) public void handleDurableTopic(String message) { System.out.println("持久订阅收到通知:" + message); }
持久订阅注意点:
同一个 broker 上 clientId 需要唯一 同一个 clientId + subscription 代表同一个持久订阅
消息选择器
消息选择器可以按消息属性过滤。
发送:
jmsTemplate.convertAndSend("order.queue", message, jmsMessage -> { jmsMessage.setStringProperty("bizType", "order"); jmsMessage.setStringProperty("level", "important"); return jmsMessage; });
消费:
@JmsListener( destination = "order.queue", selector = "bizType = 'order' AND level = 'important'" ) public void handleImportantOrder(OrderCreatedMessage message) { System.out.println("收到重要订单消息:" + message); }
选择器适合按少量稳定属性过滤。
如果路由规则很复杂,通常更适合拆分队列或 Topic。
延迟消息
ActiveMQ Classic 支持调度消息。
常见属性:
| 属性 | 作用 |
|---|---|
AMQ_SCHEDULED_DELAY |
延迟多久投递 |
AMQ_SCHEDULED_PERIOD |
重复投递周期 |
AMQ_SCHEDULED_REPEAT |
重复次数 |
AMQ_SCHEDULED_CRON |
Cron 表达式 |
发送延迟消息:
import org.apache.activemq.ScheduledMessage; jmsTemplate.convertAndSend("order.timeout.queue", message, jmsMessage -> { jmsMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 30 * 60 * 1000L); return jmsMessage; });
表示 30 分钟后投递。
Broker 需要开启 scheduler 支持。
死信队列
ActiveMQ Classic 默认有死信队列。
常见默认名称:
ActiveMQ.DLQ
消息可能进入死信队列的常见原因:
- 消费者重复失败
- 消息过期
- 消息被回滚多次
- 达到最大重投递次数
ActiveMQ 常见处理链路:
消费者处理失败 | v Session rollback 或监听器抛异常 | v Broker 重新投递 | v 超过最大重投递次数 | v 进入 DLQ
死信队列适合:
- 保留异常消息
- 后台补偿处理
- 人工排查
- 告警通知
Redelivery 重投递
ActiveMQ 客户端可以设置重投递策略。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.RedeliveryPolicy; ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616"); RedeliveryPolicy policy = new RedeliveryPolicy(); policy.setMaximumRedeliveries(3); policy.setInitialRedeliveryDelay(1000); policy.setRedeliveryDelay(2000); policy.setUseExponentialBackOff(true); policy.setBackOffMultiplier(2.0); factory.setRedeliveryPolicy(policy);
含义:
| 配置 | 说明 |
|---|---|
maximumRedeliveries |
最大重投递次数 |
initialRedeliveryDelay |
首次重投递延迟 |
redeliveryDelay |
重投递间隔 |
useExponentialBackOff |
是否指数退避 |
backOffMultiplier |
退避倍数 |
重投递次数耗尽后,消息通常会进入 DLQ。
Spring 事务消费
Spring JMS 可以使用事务监听容器。
@Bean public DefaultJmsListenerContainerFactory txQueueListenerContainerFactory( ConnectionFactory connectionFactory ) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setSessionTransacted(true); return factory; }
监听:
@JmsListener( destination = ActiveMqDestinations.ORDER_QUEUE, containerFactory = "txQueueListenerContainerFactory" ) public void handleWithTx(OrderCreatedMessage message) { System.out.println("事务消费消息:" + message); // 方法正常结束:提交 Session // 方法抛出异常:回滚 Session,消息等待重投递 }
事务消费适合:
- 消息处理成功才确认
- 失败后触发重投递
- 和本地数据库事务配合
幂等处理
消息中间件通常更接近“至少一次”投递。
因此,消费者需要能处理重复消息。
常见做法:
消息带唯一 messageId 消费前检查处理记录 未处理则执行业务 处理成功后保存记录 重复消息直接跳过
示例:
@JmsListener(destination = ActiveMqDestinations.ORDER_QUEUE) public void handle(OrderCreatedMessage message) { String messageId = message.orderNo(); if (messageLogRepository.exists(messageId)) { return; } processOrder(message); messageLogRepository.save(messageId); }
可以用来做幂等的方式:
- 数据库唯一索引
- 消息消费日志表
- Redis
SETNX - 业务状态机
ActiveMQ 数据存储在哪里
ActiveMQ 数据存储在 Broker 节点上。
主要包括:
- 队列和主题元数据
- 持久化消息
- 订阅关系
- 事务和调度消息信息
ActiveMQ Classic 常见持久化存储是:
KahaDB
Artemis 常见持久化方式是:
Journal
Docker 部署时,需要挂载数据目录。
Classic 常见目录:
/opt/apache-activemq/data
不同镜像目录可能不同,需要以镜像说明为准。
示例:
docker run -d \ --name activemq-classic \ -p 61616:61616 \ -p 8161:8161 \ -v activemq-data:/opt/apache-activemq/data \ apache/activemq-classic:latest
如果没有挂载数据卷,容器删除后数据也会删除。
消息重启后是否保留,取决于:
消息是否持久化 目的地和 Broker 持久化配置 存储目录是否保留
管理后台常看指标
ActiveMQ 管理后台常见关注点:
| 指标 | 说明 |
|---|---|
Pending Messages |
等待消费的消息 |
Consumers |
消费者数量 |
Enqueued |
入队消息总数 |
Dequeued |
出队消息总数 |
Dispatch Queue |
已分派但未确认消息 |
Expired |
过期消息 |
DLQ |
死信消息 |
排查思路:
Pending Messages 持续增加:消费能力不足或消费者异常 Consumers 为 0:消费者未启动或监听配置错误 DLQ 增加:业务处理失败、重投递耗尽或消息过期 Enqueued 高于 Dequeued:生产速度超过消费速度
常见使用建议
Queue 和 Topic 分清楚
Queue 是任务分发。
一条消息只给一个消费者
Topic 是广播事件。
一条消息给多个订阅者
如果业务是“发短信任务”,通常选 Queue。
如果业务是“订单已支付事件”,多个系统都要收到,通常选 Topic。
JSON 优先于 Java 原生序列化
跨系统消息更适合 JSON。
原因:
- 可读性更好
- 跨语言更容易
- 版本演进更可控
- 排查消息更方便
关键消息设置持久化
发送端可以设置:
jmsTemplate.setDeliveryPersistent(true);
原生 JMS 可以设置:
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
还需要确保 Broker 持久化存储配置正常。
消费者需要幂等
消息可能重复投递。
消费者处理逻辑需要支持重复执行。
例如:
订单已处理 -> 直接跳过 订单未处理 -> 执行业务并记录处理状态
失败消息进入 DLQ
失败消息不适合无限重试。
更常见的做法:
有限次数重投递 超过次数进入 DLQ 后台补偿或人工处理
常用 API 汇总
| API / 注解 | 作用 |
|---|---|
JmsTemplate.convertAndSend(...) |
发送消息 |
@JmsListener |
监听消息 |
ConnectionFactory |
创建连接 |
Connection |
JMS 连接 |
Session |
JMS 会话 |
Queue |
点对点目的地 |
Topic |
发布订阅目的地 |
MessageProducer |
消息生产者 |
MessageConsumer |
消息消费者 |
TextMessage |
文本消息 |
MappingJackson2MessageConverter |
JSON 消息转换 |
Session.CLIENT_ACKNOWLEDGE |
客户端确认 |
session.commit() |
提交事务会话 |
session.rollback() |
回滚事务会话 |
RedeliveryPolicy |
重投递策略 |
总结
ActiveMQ 是 Java 生态里经典的 JMS 消息中间件。
它的核心模型很清晰:
Queue:点对点,一条消息一个消费者 Topic:发布订阅,一条消息多个订阅者
日常 Spring Boot 项目里,常用组合是:
spring-boot-starter-activemq JmsTemplate @JmsListener MappingJackson2MessageConverter
真正落到工程实践,需要重点关注:
- Queue 和 Topic 模型选择
- JSON 消息格式
- 消息持久化
- 事务或确认机制
- 重投递策略
- DLQ 死信队列
- 消费幂等
- 管理后台监控
ActiveMQ 比 RabbitMQ 更贴近 JMS 规范。
维护传统 Java 企业系统、对接 JMS 老系统、使用 Queue / Topic 这种经典模型时,ActiveMQ 依然有明确价值。
更多推荐




所有评论(0)