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關閉時有消息已被接收到但還沒有被簽收,那當消費者下次連接到相同的隊列時,這些消息還會被再次接受
- 生產者開啓持久化後,服務器宕機後重啓服務器,消費者也能接收到宕機前發送的消息,關閉持久化之後則不能接收到宕機前的消息。默認開啓了持久化