2.4.6消息选择器
很多时候,一个JMS客户端订阅了一个目标,但是它只想接收特定类型的消息。这种情况,消息头部和属性正好派上用场。例如,一个消费者到一个队列注册,希望接收到特定股票的消息。只要该消息包含一个股票标识的属性,那么这个功能就很容易实现。JMS客户端可以用消息选择器告诉JMS提供者它要接收某个属性值符合要求的消息。
许多选择器允许JMS客户端基于消息头部的值指定它要接收到消息。选择器使用SQL92子集的条件表达式。消息选择器使用消息头部和属性值来进行布尔计算。不符合的消息将不会投递到客户端。消息选择器不能作用于消息体。
条件表达式作为字符串参数传递给javax.jms.Session创建选择器的方法。这些条件表达式使用包括标识符,字面量和操作符等从SQL92语法继承的符号。这些东西都在下面的表2.1中定义。
上面的这些东西都是用来对消息头部和属性创建查询条件的。看下面列表定义的消息。这条消息定义了两个属性,它们将被用来过滤消息。
Listing 2.4 A JMS message with custom properties
public void sendStockMessage(Session session,
MessageProducer producer,Destination destination,String payload,
String symbol,double price)throws JMSException
{
TextMessage textMessage = session.createTextMessage();
textMessage.setText(payload);
textMessage.setStringProperty("SYMBOL", symbol);
textMessage.setDoubleProperty("PRICE", price);
producer.send(destination, textMessage);
}
现在让我们来看一些使用消息选择器的例子。
Listing 2.5 Filter messages using the SYMBOL header
...
String selector = "SYMBOL = 'AAPL'";
MessageConsumer consumer =
session.createConsumer(destination, selector);
...
列表2.5的程序定义了一个匹配苹果公司消息的选择器。这个消费者只会接收到匹配该选择器的消息。
Listing 2.6 Filter messages using both the SYMBOL and PRICE headers
...
String selector = "SYMBOL = 'AAPL' AND PRICE > "
+ getPreviousPrice();
MessageConsumer consumer =
session.createConsumer(destination, selector);
...
上面的选择器匹配苹果公司并且价格高于之前价格的股票消息。这个选择器将会显示那些价格在上涨的股票消息。但是,如果你对股票消息的时效性有要求,那么可以看看下面的例子。
Listing 2.7 Filter messages using headers
...
String selector = "SYMBOL IN ('AAPL', 'CSCO') AND PRICE > "
+ getPreviousPrice() + " AND PE_RATIO < "
+ getCurrentAcceptedPriceToEarningsRatioThreshold();
MessageConsumer consumer =
session.createConsumer(destination, selector);
...
最后的例子2.7定义了一个更复杂的选择器。这个选择器可以用来匹配苹果及思科公司那些正在增长的,并且市盈率小于当前可接受值的消息。
上面的例子对于你开始使用消息选择器来说已经足够了。但是如果你想要更多的信息,可以参考JMS消息的Javadoc。
消息体
消息体,也就是负载,JMS为它定义了六种Java类型。使用这些Java对象,信息就可以通过消息负载发送出去。
- Message----基本的消息类型。用来发送没有负载,只有头部和属性的消息。最常用在简单的事件通知。
- TextMessage----负载是String类型的消息。用在发送简单文本或XML数据。
- MapMessage----使用一系列name/value(名称/值)做为它的负载。名称使用字符串,值是Java原始类型。
- BytesMessage----包含一个不能被中断字节数组作为负载。
- StreamMessage----包含一些Java原始类型的流,会按顺序被填充和读取。
- ObjectMessage----用来包含一个序列号Java对象。一般用来存储复杂Java对象,也支持Java集合。