一, 理解 JMS
1, 什么是 JMS?
JMS 即 Java 消息服务 (Java Message Service) 应用程序接口, API 是一个消息服务的标准或者说是规范, 允许应用程序组件基于 JavaEE 平台创建, 发送, 接收和读取消息. 它使分布式通信耦合度更低, 消息服务更加可靠以及异步性.
我们可以简单的理解: 两个应用程序之间需要进行通信, 我们使用一个 JMS 服务, 进行中间的转发, 通过 JMS 的使用, 我们可以解除两个程序之间的耦合.
JMS 不是消息队列, 更不是某种消息队列协议. JMS 是 Java 消息服务接口, 是一套规范的 JAVA API 接口.
1)这套规范接口由 SUN 提出, 并在 2002 年发布 JMS 规范的 Version 1.1 版本.
2)JMS 和消息中间件厂商无关, 既然是一套接口规范, 就代表这它需要各个厂商进行实现.
3)大部分消息中间件产品都支持 JMS 接口规范, eg: 可以使用 JMS API 来连接 Stomp 协议的产品(例如 ActiveMQ).
就像您可以使用 JDBC API 来连接 ORACLE 或者 MySQL 一样.
2,JMS 的消息模型
JMS 具有两种通信模式:(点对点)和(发布 / 订阅模式).
3,JMS 中消息的产生和消费
在 JMS 中, 消息的产生和消息是异步的. 对于消费来说, JMS 的消息者可以通过两种方式来消费消息.
○ 同步 : 订阅者或接收者调用 receive 方法来接收消息, receive 方法在能够接收到消息之前 (或超时之前) 将一直阻塞
○ 异步 : 订阅者或接收者可以注册为一个消息监听器. 当消息到达之后, 系统自动调用监听器的 onMessage 方法.
4, 对象模型
(1)ConnectionFactory
创建 Connection 对象的工厂, 针对两种不同的 jms 消息模型, 分别有 QueueConnectionFactory 和 TopicConnectionFactory 两种. 可以通过 JNDI 来查找 ConnectionFactory 对象.
(2) Destination
Destination, 即 消息生产者的 消息发送目标, 或者说 消息消费者的 消息来源.
对于消息生产者来说, 它的 Destination 是某个队列 (Queue) 或某个主题(Topic);
对于消息消费者来说, 它的 Destination 也是某个队列或主题(即消息来源).
所以, Destination 实际上就是两种类型的对象: Queue,Topic. 可以通过 JNDI 来查找 Destination.
(3)Connection
Connection 表示在客户端和 JMS 系统之间建立的链接(对 TCP/IP socket 的包装).
Connection 可以产生一个或多个 Session.
跟 ConnectionFactory 一样, Connection 也有两种类型: QueueConnection 和 TopicConnection.
(4) Session
Session 是我们操作消息的接口. 可以通过 session 创建生产者, 消费者, 消息等.
Session 提供了事务的功能.
当我们需要使用 session 发送 / 接收多个消息时, 可以将这些发送 / 接收动作放到一个事务中.
同样, 也分 QueueSession 和 TopicSession.
(5) 消息的生产者
消息生产者由 Session 创建, 并用于将消息发送到 Destination.
同样, 消息生产者分两种类型: QueueSender 和 TopicPublisher.
可以调用消息生产者的方法 (send 或 publish 方法) 发送消息.
(6) 消息消费者
消息消费者由 Session 创建, 用于接收被发送到 Destination 的消息.
两种类型: QueueReceiver 和 TopicSubscriber.
可分别通过 session 的 createReceiver(Queue)或 createSubscriber(Topic)来创建.
当然, 也可以 session 的 creatDurableSubscriber 方法来创建持久化的订阅者.
(7) MessageListener
消息监听器. 如果注册了消息监听器, 一旦消息到达, 将自动调用监听器的 onMessage 方法.
EJB 中的 MDB(Message-Driven Bean)就是一种 MessageListener.
5, 消息的组成
Message 主要由三部分组成, 分别是 Header,Properties 和 Body, 解释如下:
Header: 消息头, 所有类型的这部分格式都是一样的
Properties: 属性, 按类型可以分为 应用设置的属性 , 标准属性 和 消息中间件定义的属性
Body: 消息正文, 指我们具体需要消息传输的内容.
消息头
序号 | 属性名称 | 说明 | 设置者 |
1 | JMSDestination | 消息发送的目的地,是一个 Topic 或 Queue | send |
2 | JMSDeliveryMode | 消息的发送模式,分为 NON_PERSISTENT 和 PERSISTENT,即 持久化的 和 非持久化的 | send |
3 | JMSMessageID | 消息 ID,需要以 ID : 开头 | send |
4 | JMSTimestamp | 消息发送时的时间,也可以理解为 调用 send() 方法时的时间,而不是 该消息发送完成的时间 | send |
5 | JMSCorrelationID | 关联的消息 ID,这个通常用在需要回传消息的时候 | client |
6 | JMSReplyTo | 消息回复的目的地,其值为一个 Topic 或 Queue, 这个由发送者设置,但是接收者可以决定是否响应 | client |
7 | JMSRedelivered | 消息是否重复发送过,如果该消息之前发送过,那么这个属性的值需要被设置为 true, 客户端可以根据这个属性的值来 确认这个消息是否重复发送过,以避免重复处理。 | Provider |
8 | JMSType | 由消息发送者设置的个消息类型,代表消息的结构,有的消息中间件可能会用到这个,但这个并不是是批消息的种类,比如 TextMessage 之类的 | client |
9 | JMSExpiration | 消息的过期时间,以毫秒为单位,根据定义,它应该是 timeToLive 的值再加上发送时的 GMT 时间,也就是说这个指的是过期 时间,而不是有效期 | send |
10 | JMSPriority | 消息的优先级, 0-4 为普通的优化级,而 5-9 为高优先级,通常情况下,高优化级的消息需要优先发送 | send |
消息属性
消息属性的主要作用是可以对头信息进行一个额外的补充, 毕竟消息头信息: 一是有限, 二是很多不能由应用程序设定.
通常, 消息属性可以用在消息选择器的表达式里, 结合起来实现对消息的过滤.
消息属性的值只能是基本的类型, 或者这些基本类型对应的包装类型. 也就是说, 不能将一个自定义的对象作为属性值.
通常情况下, 如果能够放在 body 里的内容, 就不必放在消息属性里.
消息体
为了适应不同场景下的消息, 提高消息存储的灵活性, JMS 定义了几种具体类型的消息, 不同的子类型的消息体也不一样.
需要注意的是, Message 接口并没有提供一个统一的 getBody 之类的方法.
消息子接口定义如下:
1)TextMessage: 最简单的消息接口, 用于发送文本类的消息, 设置 / 获取其 body 的方法定义如下 setText()/getText().
2)StreamMessage: 流式消息接口, 里面定义了一系列的对基本类型的 set/get 方法,
消息发送者可以通过这些方法写入基本类型的数据,
消息接收者需要按发送者的写入顺序来读取相应的数据.
3)MapMessage: 把消息内容存储在 Map 里, 本接口定义了一系列对基本类型的的 set/get 方法,
与 StreamMessage 不同的是, 每个值都对应了一个相应的 key,
所以消息接收者不必按顺序去读取数据.
4)ObjectMessage: 将对象作为消息的接口, 提供了一个 set/get 对象的方法, 需要注意的是只能设置一个对象, 这个对象可以是一个 Collection, 但必须是序列化的.
5)BytesMessage: 以字节的形式来传递消息的接口, 除了提供了对基本类型的 set/get, 还提供了按字节方式进行 set/get.
MQ 消息队列(2)-- Java 消息服务接口(JMS)
来源: http://www.bubuko.com/infodetail-3103484.html