The JMS message is the most important concept in the JMS specification. Every concept in the JMS spec is built around handling a JMS message because it’s how business data and events are transmitted. A JMS message allows anything to be sent as part of the message, including text and binary data as well as information in the headers. As
depicted in figure 2.5, JMS messages contain two parts, including headers and a payload. The headers provide metadata about the message used by both clients and JMS providers. The payload is the actual body of the message and can hold both textual and binary data via the various message types. The JMS message is designed to be easy to understand and flexible. All the complexity of the JMS message resides in the headers.
JMS消息是JMS规范中最重要的概念。 每个在JMS规范中概念都是围绕处理一个JMS消息,因为它包含了业务数据和事件是怎么被传输的。 JMS消息允许任何内容作为其一部分发送消息,包括文本和二进制数据以及标题中的信息。 如下所示,JMS消息包含两部分,包括消息头部和消息载体(类似于我们常用的大部分协议,如http等)。消息头提供消息的接受端和发送端两个客户端和JMS规范的元数据。消息载体是消息的实际内容,并且可以保存文本和承载了各种各样数据的二进制数据(如图片,流等等)。JMS消息设计宗旨是在易于理解和可扩展。 所有的复杂的内容包含在JMS消息头中。
As mentioned previously, the complexity of a JMS message lies in the details provided by the headers. There are actually two types of headers, which are basically the same logical concept but differ semantically. Whereas a standard list of headers and methods to work with them are provided by the JMS spec, properties are designed to facilitate custom headers based on primitive Java types. Both are referred to generically as headers.
如前所述,JMS消息的复杂性位于标题提供的详细信息中。 那里实际上是两种类型的标题,基本上相同的逻辑概念,但语义上不同。JMS消息头的标准列表,是由JMS规范提供的。JMS消息头属性被设计为便于使用java类型来自定义JMS消息头。两者都被作为JMS消息头。
As shown in figure 2.5, JMS messages support a standard lists of headers and the JMS API provides methods for working with them. Many of the headers are automatically assigned. The following list describes each of these headers, and how they are assigned to the message.
如上图所示,标准的JMS消息头与JMS API提供的方法一起工作。大多数头信息是被自动分配的,接下来描述每个头的含义,以及如何被分配到消息中的
Headers set automatically by the client’s send() method:
消息头被自动设置,通过客户端掉用send方法:
JMSDestination—The destination to which the message is being sent. This is valuable for clients who consume messages from more than one destination.
JMSDeliveryMode—JMS supports two types of delivery modes for messages: persistent and nonpersistent. The default delivery mode is persistent. Each delivery mode incurs its own overhead and implies a particular level of reliability.
- Persistent—Advises the JMS provider to persist the message so it’s not lost if the provider fails. A JMS provider must deliver a persistent message once and only once. In other words, if the JMS provider fails, the message won’t be lost and won’t be delivered more than once. Persistent messages incur more overhead due to the need to store the message, and value reliability over performance.
- Nonpersistent—Instructs the JMS provider not to persist the message. A JMS provider must deliver a nonpersistent message at most once. In other words, if the JMS provider fails, the message may be lost, but it won’t be delivered twice. Nonpersistent messages incur less overhead and value performance over reliability. The delivery mode is set on the producer and is applied to all messages sent from that producer. But the delivery mode can be overridden for individual messages.
JMSDeliveryMode- JMS支持两种传递模式,持久和非持久。默认的传递模式是持久,每一个模式不仅会影响消息头而已还意味着消息的可靠性
Persistent—通知消息提供者去持久化消息。即使消息提供者挂掉,消息也不会丢失。在这个模式下,JMS提供者必须对消息进行持久化并且只进行一次。如果JMS提供者挂了,此时该JMS提供者的消息并不会丢失,但消息只能被消费者使用一次。
由于持久化消息提供了额外的可靠性保护,因此也需要更多的空间和性能消耗。
Nonpersistent - 使得JMS提供者不需求持久化消息。JMS提供者必须最多传递一次非持久消息。如果JMS提供者挂了,此时该JMS提供者的消息会丢失,但不会出现第二次。非持久消息会提供更高的性能和较低的可靠性。
传递模式在消息发送者上设置,并应用于从发送的所有消息。 但是可以针对单个消息覆盖传递模式。
JMSExpiration—The time that a message will expire. This header is used to prevent delivery of a message after it has expired. The expiration value for messages can be set using either the MessageProducer.setTimeToLive() method to set the time-to-live globally for all messages sent from that producer, or using one of the MessageProducer.send() methods to set the time-to-live locally for each message that is sent. Calling any of these methods sets the default length of time in milliseconds that a message should be considered usable, although the MessageProducer.send() methods take precedence.
The JMSExpiration message header is calculated by adding the time-to-live to the current time in GMT. By default the time-to-live is zero, meaning that the message won’t expire. If a time-to-live isn’t specified, the default value is used and the message won’t expire. If the time-to-live is explicitly specified as zero, then the same is true and the message will not expire.
This header can be valuable for time-sensitive messages. But be aware that JMS providers shouldn’t deliver messages that have expired, and JMS clients should be written so as to not process messages that have expired.
JMSExpiration—JMS消息的超时时间,这个头信息被用来阻止过期消息的传递。消息的超时值可以使用MessageProducer.setTimeToLive()方法设置该生产者发送的所有消息的生存时间,或使用一个MessageProducer.send()方法来设置单个消息的超时值。调用这两个方法都会设置时间,以毫秒为单位。
通过将生存时间添加到JMSExpiration消息头中来计算超时时间。默认情况下,超时时间为零,意味着消息不会过期。如果未指定超时时间,则使用默认值并且消息不会过期。如果超时时间明确指定为零,那么同样的消息不会过期。
此消息头对于时间敏感的消息很有用。但要注意,JMS提供者程序不应传递已过期的消息和JMS客户端应该被写入以便不处理已经过期的消息。
JMSMessageID —A string that uniquely identifies a message that’s assigned by the JMS provider and must begin with ID. The message ID can be used for message processing or for historical purposes in a message storage mechanism. Because message IDs can cause the JMS provider to incur some overhead, the producer can advise the JMS provider that the JMS application doesn’t depend on the value of this header via the MessageProducer.setDisableMessageID() method. If the JMS provider accepts this advice, the message ID must be set to null. Be aware that a JMS provider may ignore this call and assign a message ID anyway.
JMSMessageID –JMS提供者为每个消息提供了唯一标识字符串,并且必须以ID开头。 消息ID可用于消息处理或用于历史目的的消息存储机制。 因为消息ID可能导致JMS提供程序产生一些开销,消息提供者可以建议JMS提供程序JMS应用程序不依赖于这个消息头的值(通过MessageProducer.setDisableMessageID()方法设置)。如果JMS提供程序同意该建议,则消息标识必须设置为null。但JMS提供程序可以忽略此调用并始终分配消息ID。
JMSPriority—Used to assign a level of importance to a message. This header is also set on the message producer. Once the priority is set on a producer, it applies to all messages sent from that producer. The priority can be overridden for individual messages. JMS defines 10 levels of message priority, ranging from 0 (the lowest) to 9 (the highest):
* Priorities 0–4—These priorities are finer granularities of the normal priority.
* Priorities 5–9—These priorities are finer granularities of expedited priority.
JMS providers aren’t required to implement message ordering, although most do. They should simply attempt to deliver higher-priority messages before lower-priority messages.
JMSPriority - 用于为消息分配重要级别。 这个头是也设置在消息提供者者。 一旦在生产者上设置了优先级,适用于从该生产者发送的所有消息。 可以对单个消息进行单独设置。 JMS定义了10个级别的消息优先级,范围从 0(最低)到9(最高):
*优先级0-4 - 这些优先级是普通优先级。
*优先级5-9 - 这些优先级是高优先级。
JMS提供者不需要实现消息排序,尽管大部分情况是需要排序。 他们应该简单地尝试提供更高优先级的消息在低优先级消息之前。
JMSTimestamp—This header denotes the time the message was sent by the producer to the JMS provider. The value of this header uses the standard Java millis time value. Similar to the JMSMessageID header, the producer may advise the JMS provider that the JMSTimestamp header isn’t needed via the MessageProducer.setDisableMessageTimestamp() method. If the JMS provider accepts this advice, it must set the JMSTimestamp to zero.
JMSTimestamp–这个消息头表示消息由生产者发送到JMS提供程序的时间。 此标头的值使用标准Java millis时间值。 与JMSMessageID头类似,JMS提供者建议JMS生产者不设置JMSTimestamp头(通过MessageProducer.setDisableMessageTimestamp()),如果JMS生产者接受此建议,则它则将JMSTimestamp设置为零。
Header set optionally by the client:
客户端可选的头信息:
JMSCorrelationID—Used to associate the current message with a previous message.This header is commonly used to associate a response message with a request message. The value of the JMSCorrelationID can be one of the following:
* A provider-specific message ID
* An application-specific String
* A provider-native byte[] value
The provider-specific message ID will begin with the ID: prefix, whereas the application-specific String must not start with the ID: prefix. If a JMS provider supports the concept of a native correlation ID, a JMS client may need to assign a specific JMSCorrelationID value to match that expected by non-JMS clients, but this isn’t a requirement
JMSCorrelationID - 用于将当前消息与先前消息相关联。这个消息头通常用于将响应消息与请求消息。 JMSCorrelationID的值可以是以下之一:
*特定于提供者的消息ID
*应用程序特定的字符串
*提供程序自身的byte []值
提供者的消息以ID:为前缀开头,而应用程序特定的消息不能以ID:前缀开头。 如果是JMS提供者支持 native correlation ID的概念,JMS客户端可能需要分配一个特定的JMSCorrelationID值,以匹配非JMS客户端所期望的值,但是这不是必需的
JMSReplyTo —Used to specify a destination where a reply should be sent. This header is commonly used for request/reply style of messaging. Messages sent with this header populated typically expect a response, but it’s actually optional.The client must make the decision to respond or not.
JMSReplyTo —用于指定应发送消息响应。 这个信息头通常用于消息的请求/回复模式。 已发送消息使用此标题通常希望得到接受者的响应,它是可选的头信息。
客户必须做出是否作出对发送者的响应。
JMSType—Used to semantically identify the message type. This header is used by few vendors and has nothing to do with the payload Java type of the message.
JMSType— 用于语义标识消息类型。 这个头信息只有很少厂商使用并且和消息承载的Java类型无关。
Headers set optionally by the JMS provider:
JMS提供者可选的消息头:
Used to indicate the liklihood that a message was previously
delivered but not acknowledged. This can happen if a consumer fails to
acknowledge delivery, or if the JMS provider hasn’t been notified of delivery
such as an exception being thrown that prevents the acknowledgement from
reaching the provider.
用于指示消息先前的可能性交付但未确认。 如下情况可以发生,抛出了异常阻止了确认消息到达提供者,此时消费者确认传递失败或者JMS提供程序根本没有收到传递通知。
JMS MESSAGE PROPERTIES
JMS消息属性
Properties are simply additional headers that can be specified on a message. JMS provides the ability to set custom headers using generic methods. Methods are provided for working with many primitive Java types for header values including Boolean, byte, short, int, long, float, double, and also the String object type. Examples of these methods can be seen in the next listing, taken from the Message interface.
属性只是可以在消息上指定的附加标题。 JMS提供使用通用方法设置自定义标头的功能。 提供了使用许多原始Java类型处理标头值(包括布尔值,字节,短整型,长整型,浮点型,双精度型,以及String对象类型)的方法。 这些方法的示例可以在下一个列表中看到,取自Message接口。
public interface Message {
...
boolean getBooleanProperty(String name) throws JMSException;
byte getByteProperty(String name) throws JMSException;
short getShortProperty(String name) throws JMSException;
int getIntProperty(String name) throws JMSException;
long getLongProperty(String name) throws JMSException;
float getFloatProperty(String name) throws JMSException;
double getDoubleProperty(String name) throws JMSException;
String getStringProperty(String name) throws JMSException;
Object getObjectProperty(String name) throws JMSException;
...
Enumeration getPropertyNames() throws JMSException;
boolean propertyExists(String name) throws JMSException;
...
void setBooleanProperty(String name, boolean value) throws JMSException;
void setByteProperty(String name, byte value) throws JMSException;
void setShortProperty(String name, short value) throws JMSException;
void setIntProperty(String name, int value) throws JMSException;
void setLongProperty(String name, long value) throws JMSException;
void setFloatProperty(String name, float value) throws JMSException;
void setDoubleProperty(String name, double value) throws JMSException;
void setStringProperty(String name, String value) throws JMSException;
void setObjectProperty(String name, Object value) throws JMSException;
.. }
Also note the two convenience methods for working with generic properties on a message—the getPropertyNames() method and the propertyExists() method. The getPropertyNames() method returns an Enumeration of all the properties on a given message to easily iterate through all of them. The propertyExists() method is for testing whether a given property exists on a message. Note that the JMS-specific headers aren’t considered generic properties and aren’t included in the Enumeration returned by the getPropertyNames() method. There are three types of properties: custom properties, JMS defined properties, and provider-specific properties.
还要注意使用通用属性的两个方便的方法message-getPropertyNames()方法和propertyExists()方法。 的getPropertyNames()方法返回给定的所有属性的枚举消息,以便轻松地遍历所有这些。 propertyExists()方法是for测试消息上是否存在给定的属性。 注意JMS特定的头不被视为通用属性,不包括在返回的枚举中通过getPropertyNames()方法。有三种类型的属性:自定义属性,JMS定义的属性,和提供程序特定的属性
CUSTOM PROPERTIES
Custom properties are arbitrary and are defined by a JMS application. Developers of JMS applications can freely define any properties using any Java types necessary, by using the generic methods shown in the previous section (getBooleanProperty()/setBooleanProperty(), getStringProperty()/setStringProperty(), and so on).
自定义属性
自定义属性是任意的,由JMS应用程序定义。 JMS应用程序开发者可以使用任何Java类型来自由定义任何属性,使用上一节中显示的通用方法(getBooleanProperty()/setBooleanProperty(),getStringProperty()/ setStringProperty(),等等)。
JMS-DEFINED PROPERTIES
The JMS spec reserves the JMSX property name prefix for JMS-defined properties, and support for these properties is optional:
JMSXAppID—Identifies the application sending the message
JMSXConsumerTXID —The transaction identifier for the transaction within which this message was consumed
JMSXDeliveryCount—The number of message delivery attempts
JMSXGroupID—The message group of which this message is a part
JMSXGroupSeq—The sequence number of this message within the group
JMSXProducerTXID—The transaction identifier for the transaction within which this message was produced
JMSXRcvTimestamp —The time the JMS provider delivered the message to theconsumer
JMSXState—Used to define a provider-specific state
JMSXUserID —Identifies the user sending the message .
JMS定义属性
JMS规范为JMS定义的属性保留JMSX属性名称前缀
支持这些属性是可选的:
JMSXAppID - 标识发送消息的应用程序
JMSXConsumerTXID - 其中的事务的事务标识符 此消息已处理
JMSXDeliveryCount - 邮件传递尝试次数
JMSXGroupID - 此消息所属的消息组
JMSXGroupSeq - 组中此消息的序列号
JMSXProducerTXID - 其中的事务的事务标识符 此消息已生成
JMSXRcvTimestamp - JMS提供程序将消息传递到消费者的时间
JMSXState - 用于定义提供程序特定的状态
JMSXUserID - 标识发送消息的用户
The only recommendation provided by the spec for use of these properties is for the JMSXGroupID and JMSXGroupSeq properties, and that these properties should be used by clients when grouping messages and/or grouping messages in a particular order
使用这些属性规范提供的唯一建议是JMSXGroupID和JMSXGroupSeq属性,并且应使用这些属性由客户端在按照特定顺序分组消息和/或分组消息时。
PROVIDER-SPECIFIC PROPERTIES
The JMS spec reserves the JMS_<vendor-name>
property name prefix for provider specific properties. Each provider defines its own value for the <vendor-name>
placeholder. These are most typically used for provider-specific non-JMS clients and shouldn’t be used for JMS-to-JMS messaging. Now that JMS headers and properties on messages have been discussed, for what exactly are they used? Headers and properties are important when it comes to filtering the messages received by a client subscribed to a destination.
提供者特定属性
JMS规范为特定于提供程序保留JMS_ <vendor-name>
属性名称前缀属性。 每个提供者为<vendor-name>
占位符定义自己的值。这些最常用于特定于提供者的非JMS客户端和不应该用于JMS到JMS消息传递。现在已经讨论了消息上的JMS头和属性,究竟是他们使用? 涉及到接受客户端发的消息进行过滤时,标题和属性很重要。
MESSAGE BODY
JMS defines six Java types for the message body, also known as the payload. Through the use of these objects, data and information can be sent via the message payload.
JMS为消息体定义了六种类型载体,通过这个类型,你可以发送各种各样的数据。
1 Message —The base message type. Used to send a message with no payload, only
headers and properties. Typically used for simple event notification.
最基础的消息体,没有数据载体。仅仅包含了消息体和属性,一般用做简单的时间通知。
2 TextMessage —A message whose payload is a String. Commonly used to send simple
textual and XML data.
TextMessage文本消息 字符串数据载体。一般用来发送简单的文本,XML数据。
3 MapMessage —Uses a set of name/value pairs as its payload. The names are of
type String and the values are a Java primitive type.
MapMessage key-value键值队作为数据载体。key一般使用字符串,value可以为Java原始类型。
4 BytesMessage —Used to contain an array of uninterpreted bytes as the payload.
BytesMessage 使用一个二进制数据来做数据载体。
6 StreamMessage—A message with a payload containing a stream of primitive Java types that’s filled and read sequentially.
Java原始类型的流数据
6 ObjectMessage—Used to hold a serializable Java object as its payload. Usually
used for complex Java objects. Also supports Java collections.
序列化后的完整Java类。通过使用与复杂Java类型。也支持集合