JMS 应用程序由以下元素组成:
- JMS 客户机。 用 JMS API 发送和接收消息的 Java 程序。
- 非 JMS 客户机。 认识到传统程序通常整个 JMS 应用程序的一部分是非常重要的,在规划时必须优先考虑它们的存在。
- 消息。就JMS 应用程序设计而言,通过JMS 和非 JMS 客户机所交换的消息的格式和内容是完整的。
- JMS 提供者。 如前所述,JMS 定义了一组接口,供应者必须提供特定于其 MOM 产品的具体实现。
- 管理对象。 消息系统提供者的管理员创建的、独立于提供者的专有技术的对象。
MOM 产品的提供者在实现消息时使用的机制和技术有很大不同。为了保持 JMS 客户机的可移植性,实现了 JMS 接口的对象必须与提供者的专有技术隔离。
完成这项任务的机制是 管理对象。这些实现 JMS 接口的对象由提供者的消息系统的管理员创建,并被放置在 JNDI 名字空间中。
然后由 JMS 程序检索这些对象,通过它们实现的 JMS 接口访问这些对象。JMS 提供者必须提供允许创建受管理对象及它们在 JNDI 名字空间中的存放地的工具。
有两种受管理对象:
ConnectionFactory
:用于创建到提供者的底层消息系统的连接。Destination
:用 JMS 客户机来指定正发送消息的目的地或正接收消息的来源。
尽管受管理对象本身就是特定于提供者实现的类的例子,但可以使用可移植机制(JNDI)检索它们,并且可以通过可移植接口(JMS)访问它们。JMS 程序只需要知道管理对象的 JNDI 名称和 JMS 接口类型即可,无需了解特定于提供者的知识。
JMS 定义了一组封装各种消息概念的高级接口。而这些接口又因为两个消息域——PTP 和 pub/sub——进行了进一步地定义和定制。
高级接口包括:
ConnectionFactory
:一个创建Connection
的受管理对象。Connection
:连接到提供者的活动连接。Destination
:一个封装消息目的地的身份的受管理对象,如消息的来源地和发送地。Session
:发送和接收消息的单线程环境。为了简化,并且因为Session
控制事务的缘故,通过多个线程进行并发访问受到了限制。可以将多个Session
用于多线程应用程序。MessageProducer
:用于发送消息。MessageConsumer
:用于接收消息。
下表列出了从每一个高级接口继承的特定于域的接口。
高级接口 | PTP 域 | Pub/sub 域 |
---|---|---|
ConnectionFactory | QueueConnectionFactory | TopicConnectionFactory |
Connection | QueueConnection | TopicConnection |
Destination | Queue | Topic |
Session | QueueSession | TopicSession |
MessageProducer | QueueSender | TopicPublisher |
MessageConsumer | QueueReceiver ,QueueBrowser | TopicSubscriber |
一个典型的 JMS 程序要经过以下步骤才能开始产生和使用消息:
- 通过 JNDI 查询
ConnectionFactory
。 - 通过 JNDI 查询一个或者多个
Destination
。 - 用
ConnectionFactory
创建一个Connection
。 - 用
Connection
创建一个或者多个Session
。 - 用
Session
和Destination
创建所需要的MessageProducer
和MessageConsumer
。 - 启动
Connection
。
JMS 为不同类型的内容提供了几种消息类型,但所有消息都是从 Message
接口派生出来的。
Message
分为三个组成部分:
- header 是一组标准字段,客户机和提供者都用它们来标识和路由消息。
- Properties 提供了一个给消息添加可选标题字段的实用工具。如果应用程序需要用标准标题字段没有提供的方法对消息进行归类或分类,那么可以为消息添加一个属性来实现这种归类和分类;提供了
set<Type>Property(...)
和get<Type>Property(...)
方法来设置和获得各种 Java 类型的属性,其中包括Object
。JMS 定义了提供者可以选择性提供的一组标准属性。 - 消息的 body 包含将 发送到接收应用程序的内容。每一个消息接口都专用于它所支持的内容类型。
header字段
下面列出了 Message
的每一个标题字段的名称、它对应的 Java 类型和字段的描述:
JMSMessageID
——类型为string
惟一标识提供者发送的每一条消息。这个字段是在发送过程中由提供者设置的,客户机只能在消息发送后才能确定消息的
JMSMessageID
。JMSDestination
——类型为Destination
消息发送的
Destination
,在发送过程中由提供者设置。JMSDeliveryMode
——类型为int
包含值
DeliveryMode.PERSISTENT
或者DeliveryMode.NON_PERSISTENT
。持久性消息被传输并且只被传输一次,非持久性消息最多被传输一次。要知道“最多一次”包括根本不传输。非持久性消息在应用程序或者系统出故障时被提供者弄丢。因此要格外小心,确保持久性消息不受故障的影响。这比开销通常被认为是发送持久性消息方面的开销,在决定消息的发送模式时,必须仔细考虑,在可靠性和性能之间进行权衡。JMSTimestamp
——类型为long
提供者发送消息的时间,由提供者在发送过程中设置。
JMSExpiration
——类型为long
消息失效的时间。这个值是在发送过程中计算的,是发送方法的生存时间(time-to-live)值和当前时间值的和。提供者不应发送过期的消息。值 0 表明消息不会过期。
JMSPriority
——类型为int
消息的优先级,由提供者在发送过程中设置。优先级 0 的优先级最低,优先级 9 的优先级最高。
JMSCorrelationID
——类型为string
通常用来链接响应消息与请求消息,由发送消息的 JMS 程序设置。响应来自另一个 JMS 程序的消息的 JMS 程序将正响应消息的
JMSMessageID
拷贝到这个字段中,这样,正作出响应的程序就可以与它所发出的特定请求的响应相 关联。JMSReplyTo
——类型为Destination
请求程序用它来指出回复消息应发送的地方,由发送消息的 JMS 程序设置。
JMSType
——类型为string
JMS 程序用它来指出消息的类型。一些提供者维护着一个消息类型仓库,并用该字段引用仓库中的定义类型,在这里,JMS 程序不应该使用这个字段。
JMSRedelivered
——类型为boolean
指出消息被过早地发送给了 JMS 程序,程序不知道消息的接收者是谁;由提供者在接收过程中设置。
有五种消息正文格式,每一种格式都是由一个扩展 Message 的接口定义的。这些接口是:
StreamMessage
:包含一组 Java 原始值,这些值是通过标准流操作按顺序进行填充和读取的。MapMessage
:包含一组名称-值( name-value )对,其中名称是string
的类型,值是 Java 原始值。TextMessage
:包含一个String
。ObjectMessage
:包含一个Serializable
Java 对象,可以使用 JDK 1.2 的 collection类。BytesMessage
:包含一些未解释字节;允许对正文进行编码来匹配现有的消息格式。
每一个提供者都提供了一些特定于实现这些接口的其产品的类。一定要注意的是, JMS 规范命令提供者必须准备接收和处理不属于它自己的 Message
类的实例的 Message
对象。
尽管提供者处理这些“外来”对象时不能像处理自己对象那样有效,但他们必须处理这些对象来确保与所有 JMS 提供者的互操作性。