JMS消息只有在被确认之后,才认为已经成功的被消费了。消息的成功消费通常包含三个阶段:客户接收消息,客户处理消息和消息被确认。
一 事务性会话
在事务性会话中,当一个事务被提交的时候,确认自动发生;即只需设置Session.SESSION_TRANSACTED。
一般而言,在创建事务性Session的时候:
Connection.createSession(是否支持事务,应答模式)
如果第一个参数设置为true,即事务性会话,那么不需要显示设置第二个参数: 应答模式.
Session.SESSION_TRANSACTED,因为创建会话的第一个参数设置为true,就代表着应答模式为Session.SESSION_TRANSACTED,而且第二个参数也没有意义,可以忽略此参数,比如你设置成了AUTO_ACKNOWLEDGE,对于会话来说没有任何意义,因为会被忽略。
如何提交会话?
Session.commit();
测试:
产生消息:
public class MessageSender {
public staticvoid main(String[] args) throws JMSException {
ConnectionFactoryconnectionFactory = new ActiveMQConnectionFactory("tcp://192.168.3.200:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.TRUE, Session.SESSION_TRANSACTED);
Destination dest = session.createQueue("animals");
MessageProducerproducer = session.createProducer(dest);
MapMessage message = null;
for (int i = 1; i <= 6; i++) {
message = session.createMapMessage();
message.setIntProperty("ackCode", Session.CLIENT_ACKNOWLEDGE);
message.setString("MSG---" + i, "Product ID---"+i);
producer.send(message);
}
session.close();
connection.close();
}
}
我们并没有提交消息,那么我们查看是否产生了6条消息
如果我们调用Session,commit();结果呢?这下肯定就有了。
二 非事务性会话
在非事务性会话中,消息何时被确认取决于创建会话的应答模式---
acknowledgement
Acknowledgement模式有三个可选值:
# AUTO_ACKNOWLEDGE
当客户端成功接受到消息,就会自动确认收到消息,比如receive方法或者MessageListener.onMessage方法,这方式就是一条消息确认一次。
public class MessageReciver {
public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.3.201:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("animals");
MessageConsumer consumer = session.createConsumer(destination);
int i = 0;
MapMessage message = null;
while (i < 6) {
i++;
message = (MapMessage) consumer.receive();
System.out.println("消息: "+message.getString("MSG---" + i));
}
session.close();
connection.close();
}
}
# CLIENT_ACKNOWLEDGE
客户端必须通过Message明确调用acknowledge方法确认收到消息
public class MessageReciver {
public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.3.201:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE,Session.CLIENT_ACKNOWLEDGE);
Destination destination = session.createQueue("animals");
MessageConsumer consumer = session.createConsumer(destination);
int i = 0;
MapMessage message = null;
while (i < 6) {
i++;
message = (MapMessage) consumer.receive();
System.out.println("消息: "+message.getString("MSG---" + i));
message.acknowledge();
}
session.close();
connection.close();
}
}
# DUPS_OK_ACKNOWLEDGE
延迟确认提交,可能存在重复的提交。比如客户端接受了10条消息,并且已经处理了,但是因为延迟提交了,所以JMS服务端可能还没有确认。这时候假设JMS 服务器宕机,那么重启之后,可能会因为之前没有提交的消息会进行重新发送,就导致重复发送的问题。
一般重新发送会设置一个消息头:JMSRedelivered设置为true