16boke - 一路博客

消息选择

许多消息应用需要过滤和分类它们生产的消息。

在消息被发送到单个接收者的情况下,通过将标准放入消息中并在接收客户端丢弃它不感兴趣的消息来实现。

当消息被广播到许多客户端时,将选择标准放入消息头中是非常有用的,这样JMS提供商就可以知道这些标准。这样提供商就可以处理更多的过滤和路由工作,否则就需要应用来做这些工作。

JMS提供了让客户端将消息选择代理给JMS提供商的功能。这简化了客户端的工作,也可以让JMS 提供商减少时间和带宽,否则它们将会将客户端不需要的消息发送给客户端。

客户端使用消息属性将应用专有的选择标准附加到消息中。客户端用消息选择器表达式来指定消息选择标准。

3.8.1 消息选择器

JMS消息选择器让客户端通过消息头指定它感兴趣的消息。只有头和属性匹配了选择器 的消息才会被转发。“不转发”的语义随着使用的MessageConsumer的不同而有所不同。参见5.8 章节“QueueReceiver”和6.11章节“TopicSubscriber”了解更详细的信息。

消息选择器不能引用消息体内的值。

当消息头字段和属性值与它们在选择器中对应的标识符匹配时,如果选择器计算值为true,那么消息选择器匹配了一个消息。

3.8.1.1消息选择器语法

消息选择器是一个String,它的语法是SQL92条件表达式语法的子集。(注:参见X/Open CAE 规范数据管理:结构化查询语言(SQL),版本2,ISBN:1‐85912‐151‐9 1996 年3月)

如果消息选择器的值是空串,那么值被看作是null,表示消息消费者没有消息选择器。

消息选择器的计算顺序是从左到右。圆括号可以改变这个顺序。

预定义的选择器文法和操作符名字用大写字符出现在这里;但是它们是大小写敏感的。

选择器可以包含:

• 文法

• 字符串用单引号括起来,在字符串内出现的单引号使用两个单引号表示(即用单引号做转义符);例如’literal’和’literal’’s’。类似java的String 文法,它们使用Unicode字符编码。

• 精确数值文法是没有小数点的数值,例如57,‐957,+62;支持Java的long取值范围。精确数值文法使用java的Integer 文法语法。

• 近似数值文法是科学计数法,例如7E3和‐57.9E2,或带小数的数值,例如7.,‐95.7 和+6.2;支持double的取值范围。近似数值文法使用java 浮点数文法语法。布尔文法是TRUE和FALSE。

• 标识符

• 标识符是无限长的字符串,它必须以java标识符开始字符开头;下述的所有字符必须是java 的标识符局部字符(part character)。标识符开头字符可以是方法Character.isJavaIdentifierStart 返回true的任何字符。包

括’_’和’$’。标识符局部字符是方法Character.isJavaIdentifierPart返回true的任何字符。

• 标识符不能是NULL,TRUE或FALSE。

• 标识符不能是NOT,AND,OR,BETWEEN,LIKE,IN,IS或ESCAPE。

• 标识符可以是头字段引用或属性引用。消息选择器中的属性值类型与用于设置属性的类型一致。如果引用了消息中不存在的属性,那么它的值是NULL。在选择器重NULL 值的计算在节3.8.1.2“Null值”描述。

• 应用到属性get方法的转换不应用到那些消息选择器表达式使用的属性。例如,假定你为一个属性设置了字符串值, 如下:myMessage.setStringProperty(“NumberOfOrders”,”2”);那么下面的在消息选择器中的表达式计算值将是false ,因为字符串不能用在数学表达式中:”NumverOfOrders>1”

• 标识符是大小写敏感的。

• 消息头字段引用仅限于

JMSDeliveryMode,JMSPriority,JMSMessageID,JMSTimestamp,JMSCorrelationID和JMSType。JMSMessageID,JMSCorrelationID和JMSType值可以是null,且如果是null则被看作是NULL 值。

• 任何以“JMSX”开头的名字是JMS定义的属性名。

• 任何以“JMS_”开头的名字是提供商专有的属性名。

• 任何不以“JMS”开头的名字是应用专有的属性名。

• 空格和Java定义的一样:空格,水平tab,格式填充符(form feed)和行结束符。

• 表达式:

• 选择器是条件表达式;选择器计算为true则匹配,计算为false 获未知则不匹配。

• 算术表达式由算术表达式,算术运算符,值是数值的标识符和数值文法组成。

• 条件表达式由条件表达式,比较运算符,逻辑运算符,值是布尔的标识符和布尔文法组成。

• ()用于改变表达式计算的顺序。

• 逻辑运算符的顺序优先级:NOT,AND,OR

• 比较运算符:=,>,>=,<,<=,<>(不等于)

• 只有类似类型的值才可以进行比较。用于比较精确数值和近似数值的表达式是有效的表达式(类型转换的要求由Java 数值提升规则(译者注:即低精度向高精度自动转换)定义)。如果比较非类似类型的值,那么返回false。如果类 型的值是NULL,那么表达式的值是未知。

• String和Boolean 比较只能使用=和<>。有且只有两个字符串有相同的字符序列,它们才是相等的。

• 算术运算符的优先顺序:

• +,-(一元)

• *,/(乘和除)

• +,-(加法和减法)

• 算术运算符必须使用java数值提升

• arithmetic‐exp1 [NOT] BETWEEN arithmetic‐exp2 AND arithmetic‐exp3(比较操作)

• “age BETWEEN 15 AND 19”等价于”age >= 15 AND age <= 19”

• “age NOT BETWEEN 15 AND 19”等价于”age < 15 OR age > 19”

• identifier [NOT] IN (string_literal1,string_literal2,…)(比较操作,identifier是String或NULL)

• “Country IN (‘UK’,’US’,’France’)”,对于’UK’返回true,对于’Peru’返回false;等价于表达式”(Country = ‘UK’) OR (Country =‘US’) OR (Country = ‘France’)”

• “Country NOT IN (‘UK’,’US’,’France’)”,对于’UK’返回false,对于’Peru’返回true;等价于表达式”NOT ((Country = ‘UK’) OR(Country = ‘US’) OR (Country =‘France’))”

• 如果IN或NOT IN操作的identifier 是NULL,那么操作的结果是未知的。

• identifier[NOT] LIKE pattern‐value [ESCAPE escape‐character](比较操作,identifier是String;pattern‐value 是字符串文法,其中’_’代表任意单个字符;’%’代表任何字符串,包括空串;其他的字符代表自己。选项escape‐character 是单字符的字符串文法,它用于忽略在pattern‐value中’_’和’%’的特定含义。

• “phone LIKE ‘12%3’” 对于’123’或’12993’是true,对于’1234’是false

• “word LIKE ‘l_se’” 对于’lose’是true,对于’loose’是false

• “underscored LIKE ‘\_%’ ESCAPE ‘\’” 对于’_foo’是true,对于’bar’是false

• “phone NOT LIKE ‘12%3’” 对于’123’或’12993’是false,对于’1234’是true

• 如果LIKE或NOT LIKE操作的identifier 是NULL,那么操作的结果是未知的

• identifier IS NULL(测试头字段值是否为空或属性值是否缺失的比较操作)

• “prop_name IS NULL”

• identifier IS NOT NULL(测试非空头字段值或属性值是否存在的比较操作)

• “prop_name IS NOT NULL”

JMS提供者需要在呈现消息选择器时验证语法的正确性。提供语法错误的选择器的方法必须产生JMS InvalidSelectorException。JMS提供者也可以可选的在呈现选择器时提供语义检查。并非所有的语义检查都能在呈现消息选择器时执行,因为属性的类型还不知道。下面的消息选择器用消息类型是car,颜色是blue和重量大于2500lbs的消息选择器来选择消息:

“JMSType = ‘car’ AND color = ‘blue’ AND weight > 2500”

3.9 访问已发送的消息

在发送消息后,客户端可以保留和更改这个消息,但不影响已发送的消息。同一个消息对象可以被多次发送。在发送方法执行时,消息不能被客户端修改。如果修改了,则没有定义发送的结果是什么。

3.10 改变收到的消息的值

当接收到消息时,可以改变消息的头字段;但是他的属性和消息体是只读的,正如本章所述。限制只读是因为为了给JMS提供商在如何实现管理接收到的消息方面更多的自由。

例如,它们可以返回一个消息对象,这个对象引用位于内部消息缓冲区的属性条目和消息体的 值,而不需要返回一个拷贝。在调研clearBody或clearProperties方法使得消息体或属性可写后,消费者可以修改接收到的消息。如果消费者更改了接收到的消息,且消息随后被转发,那么转发的消息必须是 原始的没有被改变的消息(除了被JMS提供商为转发而更改的头和属性外,例如JMSRedilvered头和JMSXDeliveryCount 属性)。