TL;DR

  • 场景: Java 系统做异步解耦与事件驱动,需要统一理解 JMS 的消息模型、对象模型与消息类型
  • 结论: JMS 是标准 API(类似 JDBC),关键在 Queue/Topic 语义、Session 与确认/事务边界
  • 产出: 一篇可直接落地的 JMS 基础稿:概念—对象模型—消息类型—实现/版本差异速查

版本矩阵

项目说明
JMS 2.0属于 Java EE 7,API 仍在 javax.jms 命名空间
Jakarta Messaging 3.1属于 Jakarta EE 10,对应 API 命名空间为 jakarta.jms
ActiveMQ Classic完整支持 JMS 1.1
ActiveMQ Artemis基于自身协议实现,提供客户端侧 JNDI
RabbitMQ本身不是 JMS Provider,需要配套插件

JMS模式

基本介绍

JMS(Java Message Service)是Java平台提供的一套标准API,专门用于实现面向消息中间件(MOM)的编程接口。

核心特点:

  1. 跨平台性: JMS提供与具体实现无关的抽象接口
  2. 松耦合通信: 通过消息代理实现生产者和消费者的解耦
  3. 支持两种消息模型:
    • 点对点(Point-to-Point): 基于队列(Queue)
    • 发布/订阅(Publish/Subscribe): 基于主题(Topic)

JMS 消息

JMS 报文头全部字段:

  • JMSMessageID
  • JMSDestination
  • JMSDeliveryMode
  • JMSExpiration
  • JMSPriority
  • JMSTimestamp
  • JMSCorrelationID
  • JMSReplyTo
  • JMSType
  • JMSRedelivered

6 种标准消息类型:

  1. TextMessage: 最常用的消息类型,包含普通字符串内容
  2. ObjectMessage: 包含一个可序列化的Java对象
  3. MapMessage: 包含一组键值对数据
  4. BytesMessage: 包含未解释的字节流数据
  5. StreamMessage: 包含一系列Java基本类型的流数据
  6. Message: 不包含实际数据,仅包含消息头和属性

体系架构

JMS由以下元素组成:

  • JMS Provider: JMS接口的一个实现
  • JMS Client: 生产或者消费消息的Java应用程序
  • JMS Producer: 创建并发送消息的JMS客户
  • JMS Consumer: 接收消息的JMS客户
  • JMS Message: 在JMS客户之间传递的数据对象
  • JMS Queue: 缓存消息的容器
  • JMS Topic: Pub/Sub模式

对象模型

Connection Factory

连接工厂是JMS中一个重要的被管对象,负责创建和管理与JMS提供者之间的连接:

ConnectionFactory cf = (ConnectionFactory)ctx.lookup("ConnectionFactory");
Connection connection = cf.createConnection();

Session

表示一个单线程的上下文,用于发送和接收消息:

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

MessageProducer

MessageProducer 是 JMS 中用于发送消息的核心接口:

MessageProducer producer = session.createProducer(destination);
producer.send(message);

MessageConsumer

MessageConsumer 是 JMS 中的核心接口之一,代表消息消费者:

同步接收:

Message message = consumer.receive();
Message message = consumer.receive(5000);

异步接收:

consumer.setMessageListener(new MessageListener() {
    @Override
    public void onMessage(Message message) {
        // 处理消息
    }
});

错误速查

症状根因修复
NoClassDefFoundError: javax/jms/...依赖命名空间不匹配统一到一套 API
Topic 订阅收不到历史消息非持久订阅只接收订阅后消息使用 durable subscription
消费者一直阻塞未调用 connection.start()按正确顺序调用
重复消费ACK/事务边界不正确开启事务并成功 commit
消息顺序不稳定多消费者并发、预取导致乱序需要强顺序:单 consumer
ObjectMessage 反序列化失败消费端缺少同名类使用 TextMessage(JSON)