JMS Selectors用在獲取消息的時候,可以基於消息屬性和Xpath語法對消息進行過濾。JMS Selectors由SQL92語義定義。以下是個Selectors的例子:
consumer = session.createConsumer(destination, "JMSType = 'car' AND weight > 2500");
1:JMS Selectors表達式中,可以使用IN、NOT IN、LIKE等
2:需要注意的是,JMS Selectors表達式中的日期和時間需要使用標準的long型毫秒值
3:表達式中的屬性不會自動進行類型轉換,例如:
myMessage.setStringProperty("NumberOfOrders", "2");
那麼此時“NumberOfOrders > 1” 求值結果會是false
4:Message Groups雖然可以保證具有相同message group的消息被唯一的consumer順序處理,但是卻不能確定被哪個consumer處理。在某些情況下,Message Groups可以和JMS Selector一起工作,
例如:
設想有三個consumers分別是A、B和C。你可以在producer中爲消息設置三個message groups分別是“A”、“B”和“C”。然後令consumer A使用“JMXGroupID = ‘A’”作爲selector。B和C也同理。這樣就可以保證message group A的消息只被consumer A處理。需要注意的是,這種做法有以下缺點:
(1)producer必須知道當前正在運行的consumers,也就是說producer和consumer被耦合到一起。
(2)如果某個consumer失效,那麼應該被這個consumer消費的消息將會一直被積壓在broker上。
下面我們使用JMS Selectors來實現消息分組功能
- 消息生產者
MessageProducer producer = session.createProducer(destination);
for (int i=0;i<10;i++) {
TextMessage msg = session.createTextMessage("hello " + i);
if (i % 2 == 0)
msg.setStringProperty("JMSXGroupID","groupA");
else
msg.setStringProperty("JMSXGroupID","groupB");
producer.send(msg);
}
- 消費者1
MessageConsumer consumer = session.createConsumer(destination,"JMSXGroupID='groupA'");
consumer.setMessageListener(msg -> {
try {
System.out.println("Received msg:" + ((TextMessage)msg).getText());
} catch (JMSException e) {
e.printStackTrace();
}
});
- 消費者2
MessageConsumer consumer = session.createConsumer(destination,"JMSXGroupID='groupB'");
consumer.setMessageListener(msg -> {
try {
System.out.println("Received msg:" + ((TextMessage)msg).getText());
} catch (JMSException e) {
e.printStackTrace();
}
});
消費者1控制檯輸出:
Received msg:hello 0
Received msg:hello 2
Received msg:hello 4
Received msg:hello 6
Received msg:hello 8
消費者2控制檯輸出:
Received msg:hello 1
Received msg:hello 3
Received msg:hello 5
Received msg:hello 7
Received msg:hello 9
參考:《ActiveMQ in Action》、ActiveMQ(23):Consumer高級特性