前言
一个JMS消息分为:
1.消息头
2.属性
3.消息体(有效负载)
1.消息头
1.1 系统默认分配的消息头
- a. JMSDestination :Topic 和Queue用此属性标识目的地,二者都是Destination类型。
javax.jms.Message接口有对应的getJMSDestination()方法。
- b.JMSDeliveryMode:传送模式:
持久化 : javax.jms.DeliveryMode.PERSISTENT
非持久化 : javax.jms.DeliveryMode.NON_PERSISTENT
javax.jms.MessageProducer接口,中有设置该消息头的方法。
JmsTemplate设置方式如下:
JmsTemplate.setDeliveryPersistent(boolean deliveryPersistent);
- c.JMSMessageID:String类型,消息的唯一标示
- d.JMSTimeStamp:由MessageProducer在调用send时自动,设置。long类型。用于确定发送消息和该消息被消息者实际接收的时间间隔。
- e.JMSExpiration:设置消息的过期时间。
MessageProducer.setTimeToLive()//进行设置。
JmsTemplate.setTimeToLive(long timeToLive)
默认不过期,javax.jms.Message.DEFAULT_TIME_TO_LIVE(该值为0,表示永不过期)
- f.JMSRedelivered:标示该消息将重复给消费者。如果为true,表示该消息将被重新发送,仅在需要确认消息的模式下有效。
- g.JMSPriority:JMS优先级,0-4普通,5-9加急,加急会比普通优先发送。
默认优先级为javax.jms.Message.DEFAULT_PRIORITY(即为4)。
1.2 为开发者分配的消息头
- a.JMSReplayTo:设置应答队列,仅仅对Queue模式有用。
JmsTemplate没有主动设置的部分,sendAndReceive方法时会临时生成一个队列。
- b.JMSCorrelationID:业务关联ID,一般情况下用于应答,存储上一条消息的JMSMessageID,表示 是这条消息的应答。
MessageListenerAdapter.onMessage会进行设置。
- c.JMSType:可选消息头,用于标注类型和有效负载类型,非MapMessage。某些消息系统需要这个字段。
2.消息属性
类似附加消息头。可以是boolean,Byte,Short,Integer,Long,float,double,Object类型
2.1应用特定的属性(自定义数据)
一般用于消息选择器。Message接口有对应的get,set方法。
jmsTemplate 的设置方式如下:
jmsTemplate.convertAndSend(queue, obj, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws JMSException {
for (Entry<String, String> head : appendHeaders.entrySet()) {
message.setStringProperty(head.getKey(), head.getValue());
}
return message;
}
});
2.2 JMS定义的属性
默认以JMSX开头,这些消息头是可选的。
名称 | 类型 | 由谁设置 | 作用 |
JMSXUserID | String | MQ在发送时设置 | 发送消息的UserId |
JMSXAppID | String | MQ在发送时设置 | 发送消息的应用ID |
JMSXDeliveryCount | int | MQ在接收时设置 | 消息尝试发送的次数,第一次为1,第二次为2 |
JMSXGroupID | String | client(调用者)端 | 消息所属的分组ID |
JMSXGroupSeq | int | Client(调用者)端 | 消息在组中的序号,第一个消息为1,第二个消息为2 |
JMSXProducerTXID | String | MQ在接收时设置 | 消息生成时的事务ID |
JMSXConsumerTXID | String | MQ在接收时设置 | 消息被消费时的事务ID |
JMSXRcvTimestamp | long | MQ在接收时设置 | JMS把消息发送的消费者的时间 |
JMSXState | int | MQ |
假设存在一个消息仓库, 该消息仓库包含每个发送到消费者 的消息的独立副本。 这些副本的存在从最初的信息开始被送时就存在 每个副本的状态,是如下状态其中之一: 1(等待)2(就绪)3(过期)4(保留) 因为状态对生成者和消费者都无用, 所以不由他们提供。 这个状态仅仅用于在仓库中查询, JMS没有对应的API |
2.3MQ特定的消息
用于支持厂商的私有特性。我在工作中没有使用到,不做介绍。
3.消息类型
JMS提供了6个消息接口,分别是:
- Message
- BytesMessage,
- MapMessage,
- ObjectMessage(传递序列化后的消息),
- StreamMessage,
- TextMessage。
Message
若使用Message,仅仅包含消息头和消息属性。基本仅仅用作事件通知。广播,警告,或者通知 中。
TextMessage
使用setText设置有效负载。getText获取消息。
ObjectMessage
setObject方法,注意这个对象必须要序列化。
BytesMessage
原始字节流作为有效负载
设置消息类似java.io.DataInputStream和java.io.DataOutputStream方法。
BytesMessage byteMessage=Session.createByteSession();
byteMessage.writeChar('c');
byteMessage.writeInt(10);
byteMessage.writeUTF("O my god");
StreamMessage
负载为java原数据类型流.允许将null写入流。读取的顺序与写入的顺序一致。
读取时的类型转换规则如下:
写类型 | 读可转换的类型 |
boolean | boolean,String |
byte | byte,short,int,long,String |
short | short,int,long,String |
char | char,String |
long | long,String |
int | int,long,String |
float | float,double,String |
String | String,boolean,byte,short,int,long,float,double |
byte[] | byte[] |
若读取时遇到异常,尝试重新读取,需要调用reset方法,将读取指针返回到开始的地方。
MapMessage
负载为一组键值对.
JMS客户端试图读取,一个不存在的值时,该值视为null。
注意:
getObject方法会对不存在的映射放回null
大多数的原始类似取值函数会返回,java.lang.NumberFormatException。
getBoolean()方法将为null值返回false;
getString(),可能返回null,或者一个空字符串。
getChar(),会抛出java.lang.NullPointerException。
为了避免上述问题,MapMessage提供了一个itemExists()的测试方法。另外getMapNames()可以让JMS客户端列举出Key。
总结
这篇blog,基本上都是JMS消息的概念,下篇blog会介绍activemq的负载均衡的搭建,预计下周完成。