JMS消息之后被确认后,才会认为是被成功消费,消费者的消费包含三个阶段:客户端接受消息、客户端处理消息、消息被确认
消息传递域:
点对点:
1.每个消息只能有一个消息者
2.消息的生产者和消费者之间没有时间上的相关性。生产者在发送消息时,无论消费者是否处在运行状态,都可以提取消息。
事务性会话:
消息提供方、消息消费方 createSession()方法中第一个参数设置为true,(此时第二个参数不起作用),表示生成的session为事务性会话。
Session session = connection.createSession(Boolean.TRUE, Session.CLIENT_ACKNOWLEDGE);
消息提供方、消息消费方都需对session进行提交:
session.commit();
若消费提供者不commit,消息不能进入队列,消息服务方不commit,队列中消息不能签收。
消息提供方:提供10条消息
public class JmsSender {
public static void main(String[] args) {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.70.66:61616");
Connection connection=null;
try {
connection = connectionFactory.createConnection();
connection.start();
//Boolean.TRUE时,createSession方法第二个参数不起作用
//生成和消费消息的单线程上下文
Session session = connection.createSession(Boolean.TRUE, Session.CLIENT_ACKNOWLEDGE);
Destination destination = session.createQueue("first-queue1");
MessageProducer producer = session.createProducer(destination);
for (int i = 0; i < 10; i++) {
TextMessage textMessage = session.createTextMessage("hello,菲菲我是帅帅的mic"+i);
textMessage.setStringProperty("song","fangyiming");
textMessage.setStringProperty("dauger","fangyifei");
producer.send(textMessage);
}
session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
}finally {
if (connection!=null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
消息消费方:
public class JmsReceiver {
public static void main(String[] args) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.70.66:61616");
Connection connection=null;
TextMessage textMessage=null;
try {
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//获取连接时的凭证
Destination destination= session.createQueue("first-queue1");
MessageConsumer consumer = session.createConsumer(destination);
for (int i = 0; i < 10; i++) {
textMessage=(TextMessage)consumer.receive();
System.out.println(textMessage.getText()+""+textMessage.getStringProperty("song"));
}
//textMessage.acknowledge();
session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection!=null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
消费端启动后,运行结果
hello,菲菲我是帅帅的mic0fangyiming
hello,菲菲我是帅帅的mic1fangyiming
hello,菲菲我是帅帅的mic2fangyiming
hello,菲菲我是帅帅的mic3fangyiming
hello,菲菲我是帅帅的mic4fangyiming
hello,菲菲我是帅帅的mic5fangyiming
hello,菲菲我是帅帅的mic6fangyiming
hello,菲菲我是帅帅的mic7fangyiming
hello,菲菲我是帅帅的mic8fangyiming
hello,菲菲我是帅帅的mic9fangyiming
ActiveMQ管理器观察消息的变化:
非事务性会话:
主要是消息消费端进行设置:
createSession()方法中第一个入参设置为FALSE,第二个参数可设置为:
AUTO_ACKNOWLEDGE
CLIENT_ACKNOWLEDGE
DUPS_OK_ACKNOWLEDGE
(1)session设置为AUTO_ACKNOWLEDGE时:
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
当客户端成功从receive()方法返回后以后,会话会自动确认该消息
(2)session设置为CLIENT_ACKNOWLEGE时:
客户端通过调用消息的textMessage.acknowledge()方法确认消息(或签收消息,消息从消息队列中出栈)
在这种模式中,如果一个消息消费者消费一共是10个消息,那么消费了5个消息,然后在第五个消息上进行textMessage.acknowledge()操作,那么前五条会被签收,后五条不会,需继续留在队列中。
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
第五条消息消费时,消息进行acknowledge()操作:
消费端代码:
public class JmsReceiver {
public static void main(String[] args) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.70.66:61616");
Connection connection=null;
TextMessage textMessage=null;
try {
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.CLIENT_ACKNOWLEDGE);
//获取连接时的凭证
Destination destination= session.createQueue("first-queue1");
MessageConsumer consumer = session.createConsumer(destination);
for (int i = 1; i <=10; i++) {
textMessage=(TextMessage)consumer.receive();
if (i==5){
textMessage.acknowledge();
}
System.out.println(textMessage.getText()+"====>"+textMessage.getStringProperty("song"));
}
//textMessage.acknowledge();
//session.commit();
session.close();
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection!=null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
第一次运行后:
管理系统队列中消息处理情况
其控制台的结果为:
hello,菲菲我是帅帅的mic0====>fangyiming
hello,菲菲我是帅帅的mic1====>fangyiming
hello,菲菲我是帅帅的mic2====>fangyiming
hello,菲菲我是帅帅的mic3====>fangyiming
hello,菲菲我是帅帅的mic4====>fangyiming
hello,菲菲我是帅帅的mic5====>fangyiming
hello,菲菲我是帅帅的mic6====>fangyiming
hello,菲菲我是帅帅的mic7====>fangyiming
hello,菲菲我是帅帅的mic8====>fangyiming
hello,菲菲我是帅帅的mic9====>fangyiming
第二次运行消费端:
控制台打印结果为:
hello,菲菲我是帅帅的mic5====>fangyiming
hello,菲菲我是帅帅的mic6====>fangyiming
hello,菲菲我是帅帅的mic7====>fangyiming
hello,菲菲我是帅帅的mic8====>fangyiming
hello,菲菲我是帅帅的mic9====>fangyiming
可以看到前五条消息已被签收(消息已出栈),而后五条还存在队列中,故第二次运行还能打印出来。
(2)session设置为DUPS_OK_ACKNOWLEDGE时:延迟签收