public class QueueTest {
//编写消息的发送端-----生产者
@Test
public void test1() throws Exception{
//创建链接工厂对象
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//从工厂中获取一个链接对象
Connection connection = connectionFactory.createConnection();
//获取session对象 第一个参数为事务,第二个参数为签收
//如果事务设置为true,则需要调用commit方法提交事务
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//通过session对象创建目的地(主题/队列)
Destination destination = session.createQueue("queue");
//通过session对象创建消息的发送者(生产者)
MessageProducer producer = session.createProducer(destination);
//开启持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//连接MQ服务
connection.start();
//通过session创建消息对象
TextMessage message = session.createTextMessage("ping");
//设置消息属性
message.setStringProperty("c01", "vip");
//MapMessage消息对象
MapMessage mapMessage = session.createMapMessage();
mapMessage.setString("key", "value");
//设置消息是否持久化 默认开启了持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//发送消息
producer.send(message);
producer.send(mapMessage);
//关闭相关资源
producer.close();
session.close();
connection.close();
}
//编写消息的接收端-----消费者
@Test
public void test2() throws Exception{
//创建链接工厂对象
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//从工厂中获取一个链接对象
Connection connection = connectionFactory.createConnection();
//连接MQ服务
connection.start();
//获取session对象 开启手动签收后 必须调用acknowledge方法手动签收,否则消息不会被消费
//如果开启事务,则会强制自动签收
final Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
//通过session对象创建目的地(主题/队列)
Destination destination = session.createQueue("queue");
//通过session对象创建消息的消费者
MessageConsumer consumer = session.createConsumer(destination);
//指定消息监听器
consumer.setMessageListener(new MessageListener() {
//当监听的queue中存在消息,这个方法自动执行
public void onMessage(Message message) {
if (null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("消费者接收到了textMessage消息:" + textMessage.getText());
System.out.println("消费者接收到了消息属性:" + textMessage.getStringProperty("c01"));
//客户端手动确认签收
message.acknowledge();
} catch (Exception e) {
e.printStackTrace();
}
}
if (null != message && message instanceof MapMessage){
MapMessage mapMessage = (MapMessage) message;
try {
System.out.println("消费者接收到了mapMessage消息:" + mapMessage.getString("key"));
//客户端手动确认
message.acknowledge();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
while(true) {
}
}
}
总结:
- 在使用Queue队列处理消息时,无论消费者在消息产生前和产生后开启,消息都能够接收到,即消费者开启前的消息不会丢失
- 在获取Session对象时如果事务设置为true,则需要调用commit方法提交事务
- 在获取Session对象时如果开启手动签收,必须调用acknowledge方法手动签收,否则消息不会被消费
- 如果开启事务,则会强制自动签收,即当事务被成功提交则消息被自动签收,如果事务回滚,则消息会被再次传送。创建Session对象的第二个签收参数无效
- 如果在Session关闭时有消息已被接收到但还没有被签收,那当消费者下次连接到相同的队列时,这些消息还会被再次接受
- 生产者开启持久化后,服务器宕机后重启服务器,消费者也能接收到宕机前发送的消息,关闭持久化之后则不能接收到宕机前的消息。默认开启了持久化