JMS2.0规范中文版


1. Introduction 2. 介绍 i. JMS概述 i. 什么是消息(messaging)? ii. JMS的目标 iii. JMS域 iv. JMS不包含什么 v. Java SE和Java EE支持 ii. JMS2.0的新特性 3. 架构 i. 概述 ii. 什么是JMS应用 iii. 管理机制 iv. 两种消息风格 v. JMS APIs vi. 不同API的通用接口 vii. 传统API接口 viii. 简化API接口 i. 简化API的目标 ii. 简化API的关键特性 ix. 遗留的域特定API接口 x. 接口间的关系 xi. 发送接收消息的术语 xii. 开发一个JMS应用 i. 开发一个JMS客户端 xiii. 安全 xiv. 多线程 xv. 触发客户端 xvi. 请求/响应(Request/Reply) 4. JMS消息模型 i. 背景 ii. 目标 iii. JMS消息 iv. 消息头字段 i. JMSDestination ii. JMSDeliveryMode iii. JMSMessageID iv. JMSTimestamp v. JMSCorrelationID vi. JMSReplyTo vii. JMSRedelivered viii. JMSType ix. JMSExpiration x. JMSPriority xi. 如何设置消息头的值 xii. 覆盖消息头属性 xiii. JMSDeliveryTime v. 消息属性 i. 属性名称 ii. 属性值 iii. 使用属性 iv. 属性值转换 v. 属性转为对象 Table of Contents vi. 属性迭代 vii. 清除消息属性值 viii. 不存在的属性 ix. JMS定义的属性 x. 提供者相关的属性 xi. JMSXDeliveryCount vi. 消息确认 vii. 消息接口 viii. 消息选择 i. 消息选择器 i. 消息选择器语法 ii. Null值 iii. 特别注意 ix. 访问发送的消息 x. 修改接收的消息的值 xi. JMS消息体 xii. JMS消息接口的提供者实现 5. 消息域 6. 受管对象 i. 概述 ii. 目的地(Destination) iii. 连接工厂(ConnectionFactory) 7. 连接到JMS提供者 8. 发送消息 9. 接收消息 10. 其他JMS功能 11. JMS异常 12. JMS应用服务器功能 13. 在Java EE应用中使用JMS API 14. 资源适配器 15. 传统JMS API的示例代码 16. 简化JMS API的示例代码 17. 修订记录 1. 文档名称:Java消息服务-JMS API是一套Java程序访问企业消息系统的API 2. 文档版本:Version 2.0 3. 规范名称:JSR-343 Java Message Service 2.0 ("Specification") 4. 原文版权:Oracle America, Inc 5. 作者信息: 版本1.1:Mark Hapner, Rich Burridge, Rahul Sharma, Joseph Fialli, Kate Stout, Sun Microsystems 版本2.0:Nigel Deakin, Oracle , 20 March 2013 在线预览版本地址: 在线文档 | 问题反馈地址:问题反馈 JMS2.0规范原文参见点击此处,原文版权参见上述链接。本翻译文档由JMS2.0规范中文翻译组于2014年7月开始翻译,版 权由原文版权所有者和翻译组共同所有。参与翻译请发邮件到:kimmking@163.com 或 提交到github仓库。 翻译组成员列表如下: kimmking(http://blog.csdn.net/kimmking) leisore(https://github.com/leisore) 香农312(http://yongchun.github.io/) longding(http://longding.iteye.com) Sky.Apollo SoMedA~y(http://jaystefanie.iteye.com/) Harrison(http://blog.sina.com.cn/kaixiangda) 完成百分比:8/16 ~ 50% 章节 页数 翻译者 状态 计划完成时间 01 4 kimmking done 2014-07-20 02 12 kimmking done 2014-07-20 03 20 kimmking doing 2014-08-03 04 8 香农312 done-check 2014-07-26 05 2 leisore done 2014-07-26 06 14 longding done-check 2014-07-26 07 10 leisore done-check 2014-07-26 08 10 Sky.Apollo done-check 2014-07-26 09 2 - - - 10 4 - - - 11 8 Harrison doing 2014-08-02 12 8 Harrison doing 2014-08-02 13 2 - - - 14 12 SoMedA~y done-check 2014-07-26 15 20 SoMedA~y doing - 16 8 - - - JMS2.0规范中文版 本规范描述Java™消息服务(JMS)的目标和功能。 JMS为Java程序创建、发送、接收和读取企业消息系统中的消息,提供了一种通用方法。 介绍 企业消息产品(有时也被称作消息中间件产品)已经成为集成企业内部操作的核心组件。它们允许独立的业务组件组成一个 可靠灵活的系统。 JMS最初被开发出来是为了访问已存在的消息产品而提供的一种标准Java API。从那时起,越来越多的消息产品被开发出 来。 JMS为Java语言的客户端和Java语言的中间层服务使用这些消息系统提供了一种通用方法。它定义了一些消息语义,以及一 组与之相应的Java接口。 由于消息传递都是点对点的,所有的JMS用户一般都可以看做客户端(client)。一个JMS应用(application)就可以看做是 由定义消息的一组应用和交换消息的一组客户端组成。 实现JMS的产品可以通过提供一个实现了JMS接口的消息提供者(provider)做到这一点。消息产品可以支持客户端使用 Java之外的编程语言。虽然这种支持超出了JMS的范畴,但是JMS的设计中还是包容了对Java之外编程语言的支持。 JMS概述 在计算机领域,消息(massaging)一词使用的非常广泛。它常常被用来描述多种操作系统概念;也常常被用来描述邮件和 传真系统;在本文,它被用来描述企业应用间的异步通信。 消息(message)在这里则指的是异步请求、响应或事件,它们被企业应用消费、而不是人类。它们携带着用于协调这些系 统的至关重要的信息。它们包含着描述特定业务操作的宝贵结构化信息。通过这些消息的交换,每个应用程序都记录着企业 发展的轨迹。 什么是消息(messaging)? JMS的目标包括: 包含实现复杂企业应用所需要的功能特性。 定义了企业消息概念和功能的一组通用集合。 最小化这些Java程序员必须学习以使用企业消息产品的概念集合。 最大化消息应用的可移植性。 JMS的目标 JMS支持企业消息产品提供两种主要的消息风格(style of messaging): 1.点对点(Point-to-Point,PTP)消息风格允许一个客户端通过一个叫“队列(queue)”的中间抽象发送一个消息给另一个客 户端。发送消息的客户端将一个消息发送到指定的队列中,接收消息的客户端从这个队列中抽取消息。 1.发布订阅(Publish/Subscribe,Pub/Sub)消息风格则允许一个客户端通过一个叫“主题(topic)”的中间抽象发送一个消 息给多个客户端。发送消息的客户端将一个消息发布到指定的主题中,然后这个消息将被投递到所有订阅了这个主题的客户 端。 JMS域 JMS不包含如下功能: 负载均衡/容错:一些消息产品支持多个相互协作的客户端实现一个严格的业务。JMS API不具体指定这些客户端如何协 作来完成某个单独统一的业务。 错误/公告通知:很多消息产品定义了用于提供给客户端出错异步通知或系统事件的系统消息。JMS暂不考虑标准化这类 消息。在本文下面的指引中可以看到,JMS客户端不使用这种消息因而避免了由此引入的移植性问题。 管理机制:JMS没有定义管理消息产品的API。 安全:JMS没有制定控制消息隐私和完整性的API。同样也没有指定如何分发数字签名和密钥给客户端。安全问题应该作 为JMS提供者特定的特性考虑,而不是由客户端的JMS API来控制。 传输协议(Wire Protocol):JMS没有定义消息的传输格式协议。 消息类型仓库(Message Type Repository):JMS没有定义存储消息类型定义的仓库,而且也没有指定用于创建消息 类型定义的语言。 JMS不包含什么 JMS API被设计成既适用于标准版Java平台(Java SE)的Java客户端应用,也适用于企业版Java平台(Java EE)上的 Java中间层服务。 JMS提供者必须提供对Java SE上的Java客户端应用的支持。而具体的某个JMS提供者是否提供对Java EE上的Java中间层 服务的支持,则是可选的。 但是Java EE规范要求一个完整的Java EE平台实现必须包含一个同时支持Java SE和Java EE平台的JMS提供者。 Java EE为消息应用引入了很多超出JMS规范的额外特性,例如消息驱动beans(message-driven beans,MDBs)和JTA事 务。Java EE同时也对JMS API的使用强加了一些约束。 在Java EE应用中使用JMS的更多信息,参见第12章“在Java EE应用中使用JMS API”。 Java SE和Java EE支持 关于JMS2.0的新特性、变更和说明的详细介绍列表,参见附录A.1章节“版本2.0的变更列表”。这里提供简单的摘要: JMS2.0规范现在要求JMS提供者同时实现点对点和发布订阅。 如下的新消息特性是JMS2.0新增的: 延迟投递:消息生产者现在可以指定一个消息不立即投递而是在特定的时间间隔以后投递 新添加的发送方法运行应用异步的发送消息 JMS提供者现在必须设置JMSXDeliveryCount消息属性 如下变更是为了改进扩展性: 持久订阅或非持久订阅现在可以是“共享的”,共享的订阅可以有多个消费者 以下的变更是为了简化JMS API的使用: Connection,Session和其他带有close()方法的对象现在实现了java.lang. AutoCloseable接口,这允许它们被用于Java SE7的try-with-resources语句中 增加了一个新的简化API,相对于标准API更加简单,特别是用于Java EE应用的时候 添加了新的方法用于创建session,而无需提供过多的参数 虽然创建非共享持久订阅时Client ID还是必须的,但是现在创建共享持久订阅时Client ID是可选的 一个名为getBody的新方法添加到Message,它允许直接从消息中抽取内容而不需要预先将其转换到一个子类型 本规范中添加了完整的一个章节(第十二章)来描述在Java EE web或EJB容器中使用JMS API时所需要的额外约束和行为。 这些信息仅仅在EJB和Java EE平台规范中可用。 本规范中添加了完整的一个章节(第十三章)来建议JMS提供者包含一个资源适配器,以及一些activation属性。 新的方法以及添加Session,Session在一个持久订阅上返回一个MessageConsumer。以前的版本,应用只可以包含一个“域 特定”的TopicSubscriber对象,现在它以及不建议使用了。 本规范将在多处作以说明。 JMS2.0的新特性 本章描述基于消息的应用环境,以及在此环境中JMS所扮演的角色。 架构 本章描述基于消息的应用环境,以及在此环境中JMS所扮演的角色。 概述 一个JMS应用由如下几个部分组成: JMS客户端-发送和接收消息的Java程序。 非JMS客户端-使用消息系统原生的客户端API代替JMS的客户端。如果程序早于JMS就可用,则它可能同时包含JMS客 户端和非JMS客户端。 消息-每个应用都定义了一组消息,用于多个客户端中间的消息通信。 消息提供者-实现了JMS的消息系统,作为一个完整的消息产品,它还应该提供其他的管理控制功能。 受管对象(Administrated Objects)-管理员创建、然后预先配置好给客户端使用的JMS对象。 什么是JMS应用 我们期望每个JMS提供者都各自使用不同的具体消息技术实现,同时也希望每个消息系统在安装和管理上有不同的实现。 如果JMS客户端是可移植的,那么它们必须要与具体JMS提供者中的专有内容相隔离。可以通过如下方式实现这一点:JMS 提供者的管理员使用提供者相关的工具来创建和定制受管对象,然后客户端再通过可移植性的JMS接口来使用这些对象。 JMS受管对象分为两种: ConnectionFactory:客户端使用这个对象创建到提供者的连接 Destination:客户端使用这个对象来指定发送或接收消息的目的地 管理员可以在JNDI命名空间中配置这些受管对象。 一般情况JMS客户端可以从相关文档中找到所需要的JMS受管对象,以及这些对象的JNDI名称应该如何提供给客户端。图2- 1展示了一般情况下JMS管理机制是如何工作的。 图2-1 JMS管理机制 管理机制 JMS应用可以使用点对点(PTP)或发布订阅(Pub/Sub)消息风格(messaging style)。后面的章节会详细描述这两种消 息风格。当然也可以在同一个JMS应用中同时使用这两个消息风格。消息风格也通常被称为消息域(message domain)。 JMS提供这两种消息域,因为它们代表着两种常用的消息模型。 在使用JMS API时,开发者可以使用同时支持这两种消息模型的接口和方法。但是使用这两种不同的模型时,消息系统的行 为可能会不同,因为这两个消息模型有着不同的语义。这些语义的不同将在第4章“消息域”中描述。 两种消息风格 由于历史的原因,JMS提供四组用于发送和接收消息的接口。 JMS1.0定义了两个域相关的API,一个用于点对点的消息处理(queue),一个用于发布订阅的消息处理(topic)。尽管由 于向后兼容的理由这些接口一直被保留在JMS中,但是在以后的API中应该考虑被废弃掉。 JMS1.1引入了一个新的统一的一组API,可以同时用于点对点和发布订阅消息模式。这也被称作传统API。 JMS2.0引入了一组简化API,它拥有传统API的全部特性,同时接口更少、使用更方便。 以上每组API提供一组不同的接口集合,用于连接到JMS提供者、发送和接收消息。因此,它们共享一组代表消息、消息目的 地和其他各方面功能特性的通用接口。 所有的接口都在javaxjms包下。 JMS APIs 不同API的主要通用接口如下: Message,BytesMessage,MapMessage,ObjectMessage,StreamMessage和TextMessage:发送到JMS提供者或 从JMS提供者接收的消息 Queue:为点对点消息处理封装了消息目的地标识的受管对象 Topic: 为发布订阅消息处理封装了消息目的地标识的受管对象 Destination:Queue和Topic的通用父类型 不同API的通用接口 传统API提供的主要接口如下: ConnectionFactory:客户端用来创建连接的受管对象。简化API也会使用此接口。 Connection:客户端到JMS提供者之间的活动连接。 Session:发送和接收消息的一个单线程上下文。 MessageProducer:由Session创建的对象,用于发送消息到Queue或Topic MessageConsumer:由Session创建的对象,用于接收Queue或Topic中的消息 图2-2 传统API概述 传统API接口 简化API与传统API提供的消息功能是一样的,但是它需要的接口更少、使用更方便。 简化API提供的主要接口如下: ConnectionFactory:客户端用来创建连接的受管对象。传统API也会使用此接口。 JMSContext:客户端到JMS提供者之间的活动连接,以及发送和接收消息的一个单线程上下文。 JMSProducer:由JMSContext创建的对象,用于发送消息到Queue或Topic JMSConsumer:由JMSContext创建的对象,用于接收Queue或Topic中的消息 图2-3 简化API概述 在简化API中,一个JMSContext对象封装了传统API中Connection和Session两个对象的行为。尽管本规范提到JMSContext 拥有潜在的“Connection”和“Session”,但实际上简化API中并不使用这两个接口。 简化API接口 简化API有如下几个目标: 减少发送和接收消息所需要的对象数量,具体就是合并JMS Connection和Session对象到一个对象。 与现有API保持一致的风格,这样使用旧API的用户可以很快的适应变化、学会使用。尽管不再需要连接(Connection) 和会话(Session)对象,但是简化API继续使用连接和会话的概念呢。 能够同时在Java EE和Java SE应用中使用。 允许资源注入,以便用于支持它们的环境中。 提供选项直接发送和接收消息体,不再需要使用javax.jms.Message对象。 移除了在方法调用时可能会需要捕获的JMSException异常。 拥有与传统API完全一致的功能特性,因此使用新的简化API的用户不需要切换到旧的传统API来实现简化API无法实现的 操作。 作为传统API的另一个选择,而不是替代品。传统API依然被保留,而且不是过时的。熟悉或喜欢传统API的开发者,可 以一直使用传统API。 简化API的目标 简化API的核心对象是javax.jms.JMSContext。它合并了传统API中的Connection和Session对象。 尽管在应用中JMSContext不暴露内部的Connection和Session对象,但Connection和Session概念依然非常重要。一个 Connection代表一个客户端到JMS服务器的物理连接,一个Session代表发送和接收消息的单线程上下文会话。JMSContext 则同时代表这两个概念。 应用发送消息时将使用JMSContext中的createProducer方法创建一个javax.jms. JMSProducer对象。此对象提供了发送消息 的API。虽然它也提供了一个类似的功能创建一个匿名的MessageProducer对象(没有具体指定Destination),但是使用 JMSProducer对象配置投递选项、消息属性和消息头更方便。 应用消费消息时可以使用JMSContext的多个方法创建一个javax.jms. JMSConsumer对象。它提供了与MessageConsumer 类似的API来从一个具体的对象或主题消费消息。消息可以被同步或异步地消费,但在Java EE web或EJB容器环境中消息只 能被同步地消费。 运行在Java EE web和EJB容器环境的应用不允许在一个连接上创建多于一个活动会话(参见章节12.2“”)。因此包含单个连 接和单个会话的JMSContext非常适用于这些应用。 运行在Java SE或Java EE应用客户端容器中的应用允许在一个连接中创建多个活动会话。这就允许同一个物理连接被多个线 程并发使用。这些需要在同一个连接创建多个会话的应用,应该先使用ConnectionFactory接口的工厂方法创建第一个 JMSContext对象,然后使用JMSContext对象的createContext方法创建额外的、共用同一个连接的多个JMSContext对象。 为了简化应用代码,JMSContext对象的方法都抛出不受检查的异常(unchecked exceptions)代替受检查的异常(checked exceptions)。 简化API的关键特性 尽管由于向后兼容的理由这些域相关的API一直被保留在JMS中,但是应用中应该使用传统API或简化API来代替这些废弃的 API。 为点对点消息处理的域相关API提供的主要接口如下: QueueConnectionFactory:客户端用于创建QueueConnection的受管对象。 QueueConnection:客户端到JMS提供者的活动连接。 QueueSession:发送和接收消息的单线程上下文。 QueueSender:由QueueSession创建,用于发送消息的对象。 QueueReceiver:由QueueSession创建,用于接收消息的对象。 图2-4 遗留的点对点域特定API概述 为发布订阅消息处理的域相关API提供的主要接口如下: TopicConnectionFactory:客户端用于创建TopicConnection的受管对象。 TopicConnection:客户端到JMS提供者的活动连接。 TopicSession:发送和接收消息的单线程上下文。 TopicPublisher:由TopicSession创建,用于发送消息的对象。 TopicSubscriber:由TopicSession创建,用于接收消息的对象。 图2-5 遗留的发布订阅域特定API概述 遗留的域特定API接口 下表概括了四种API的不同接口,以及它们之间的对应关系: 表2-1 各种API接口之间的关系 传统API 简化API 点对点域特定API 发布订阅域特定API Connection Factory Connection Factory QueueConnection Factory TopicConnection Factory Connection JMSContext QueueConnection TopicConnection Session JMSContext QueueSession TopicSession MessageProducer JMSProducer QueueSender TopicReceiver 接口间的关系 本文中术语“消费”(consume)用于表示JMS客户端获得一个消息的接收凭据;这意味着JMS提供者已经接收到一个消息, 并已经将其投递给了客户端。因为JMS支持同步和异步消息接收,所以术语“消费”用于不区分这两种情况的地方。 本文中术语“生产”(produce)是用于表示发送消息最常用的术语。它表示将一个消息发送给了JMS提供者,后者将会把消息 投递到其目的地。 发送接收消息的术语 广泛地说,一个JMS应用就是一个或多个JMS客户端相互之间交换消息。这个应用也可能包括非JMS客户端,当然非JMS客 户端使用JMS提供者的原生API而不是JMS API。 一个JMS应用可以作为一个独立单元来架构和部署。很多情况下,多个JMS客户端是逐步的添加到已经存在的应用。 JMS应用中使用的消息定义,可能是来源于JMS的、也可以是来源于应用中的非JMS部分。 开发一个JMS应用 一个使用传统API的JMS客户端典型的使用步骤如下: 使用JNDI查找一个ConnectionFactory对象 使用JNDI查找一个或多个Destination对象 使用ConnectionFactory创建一个JMS Connection对象 使用Connection创建一个或多个JMS Session对象 使用Session和Destination对象创建需要的MessageProducer和MessageConsumer对象 通知Connection对象开始投递消息 对应地,一个使用简化API的JMS客户端典型的使用步骤如下: 使用JNDI查找一个ConnectionFactory对象 使用JNDI查找一个或多个Destination对象 使用ConnectionFactory创建一个JMSContext对象 使用JMSContext创建需要的JMSProducer和JMSConsumer对象 自动开始消息投递 上述过程中描述了客户端使用JMS生产和消费消息所需要的最基本步骤。 开发一个JMS客户端 JMS不提供用于控制或配置消息完整性或消息隐私的功能特性。 这就期望各种JMS提供者来提供这些特性。同时也希望这些 服务的配置放到提供者相关的管理工具中来处理。客户端通过它们使用的部分受管对象来获得合适的安全配置。 安全 JMS理应要求所有对象都支持并发使用。考虑到对并发访问的支持会增加一些成本和复杂性,JMS的设计仅要求那些自然而 然地被多线程客户端访问的对象要支持并发。其他对象被设计成在同一时间内只能被一个逻辑线程访问。 表2-2 在传统API中使用的对象哪些支持并发 JMS对象 是否支持并发 Destination 是 ConnectionFactory 是 Connection 是 Session 否 MessageProducer 否 MessageConsumer 否 表2-3 在简化API中使用的对象哪些支持并发 JMS对象 是否支持并发 Destination 是 ConnectionFactory 是 JMSContext 否 JMSProducer 否 JMSConsumer 否 表2-4 在点对点域特定API中使用的对象哪些支持并发 JMS对象 是否支持并发 Destination 是 QueueConnectionFactory 是 QueueConnection 是 QueueSession 否 QueueSender 否 QueueReceiver 否 表2-5 在发布订阅域特定API中使用的对象哪些支持并发 JMS对象 是否支持并发 Destination 是 TopicConnectionFactory 是 TopicConnection 是 TopicSession 否 TopicPublisher 否 TopicSubscriber 否 JMS定义了一些约束会话并发使用的特定规则。这些规则用于传统API的Session对象和域特定API中的QueueSession和 多线程 TopicSession对象。它们也用于简化API中的JMSContext对象,因为它包含了一个Session。由于详细解释这些规则所需要 的知识超出了这里的内容,我们将在稍后再详细阐述,这里仅仅说明一下引入它们的依据。 有两个理由需要约束会话的并发访问。第一,会话是支持事务的实体,但是实现多线程的事务是非常困难的。第二,会话支 持异步消息消费。一个很重要的事情是,JMS不要求异步消费的客户端代码有能力处理多个并发消息。此外,如果一个会话 上创建了多个异步消费者,那么客户端不必处理每个单独消费者当前执行的情况也非常重要。这些约束对典型的客户端来 说,使得JMS更容易使用。更复杂的客户端可以使用多个会话来支持自己需要的并发场景。在传统API或域特定API里,这意 味着需要多个Session对象。在简化API里,这意味着需要多个JMXContext对象。 一些客户端被设计成周期性的被唤醒来处理等待中的消息。基于消息的应用触发机制经常被用于实现这种客户端。典型地, 这种触发经常使用等待消息数目的阈值之类的条件。 JMS不提供触发客户端执行的机制。一些提供者可能通过它们的管理工具集支持这种触发机制。 触发客户端 JMS提供一个消息头字段“JMSReplyTo”来指定返回的消息应该发送到哪个Destination。消息头字段“JMSCorrelationID”用于 将响应的消息与原始的请求关联起来。更多的信息参见章节3.4“消息头字段”。 此外,JMS提供了创建临时队列或临时主题的功能,这样可以为特定的响应创建一个唯一的Destination。 企业消息产品支持多种请求/响应风格,从最简单的“一个消息请求返回一个消息响应”,到复杂的“一个消息请求返回多个响应 者的消息流”。 相对于从架构上提供一个特定的JMS请求/响应的抽象,JMS仅仅提供了基础的功能设施,但是基于这个基础可以构建出来更 丰富的内容。 遗留的域特定API定义了请求/响应帮助类(使用JMS实现的类),这个类对点对点模式和发布订阅模式都提供了一个基本的 请求响应方式。参见章节4.17“QueueRequestor”和章节4.20“TopicRequestor”。JMS提供者和客户端可以提供更多的特殊实 现。 请求/响应(Request/Reply) JMS消息模型 企业消息产品把消息当做一个轻量级的实体,由一个消息头和一个消息体组成。消息头包括一些用于消息标识和消息路由的 字段;消息体包含被发送的应用数据。基于这个基础的格式,不同的消息产品在消息具体的定义上是显著地不同的。最主要 的区别是消息头部的语义和消息内容。一些产品使用自描述的、正规的消息数据编码格式;一些产品处理数据的方式则是完 全含糊的。一些产品提供用于标识和阐释消息内容的消息描述存储仓库;一些产品则没有这些内容。 对JMS来说,囊括所有这些内容(有时候甚至是冲突的),提供一个统一的消息模型,无疑是非常困难的。 背景 JMS消息模型有如下目标: 提供一个统一的消息API 提供一组适合已有非JMS应用创建其格式的消息的API 支持跨操作系统、机器架构和编程语言的复杂应用的开发 支持包含Java对象的消息 支持包含可扩展标记语言(Extensible Markup Language,XML)的消息(见http://www.w3c.org/XML) 目标 JMS消息由如下几个部分组成: 消息头:所有的消息都支持同样的一组消息头字段。消息头字段包含了客户端和提供者用于标识和路由消息的值。 消息属性:除了标准的消息头字段,还可以为消息提供多个可选的消息头字段。 应用相关的属性:实际上,这提供了一种添加应用相关的消息头字段的机制。 标准属性:JMS定义的一些标准的、可选的消息头字段。 提供者相关的属性:一些JMS提供者可能需要使用提供者相关的消息属性。JMS为此定义了一些命名约定。 消息体:JMS定义了几种类型的消息体,这几种消息体覆盖了当前使用中的大部分消息风格。 JMS消息 下面的多个小节详细的介绍各个消息头字段。一个消息的全部消息头字段都会传输到接收了这个消息的所有客户端。JMS不 规定它们是否也要被传输到非JMS客户端。 消息头字段 JMSDestination头字段定义了消息要被发送的目的地。 消息发送的时候,这个字段的值将被忽略。在消息被发送成功以后,这个属性将会持有发送方法里指定的值。 当一个消息被接受时,消息的目的地必须跟消息发送时指定的此字段的值是一致的。 JMSDestination JMSDeliveryMode头字段表示消息发送时指定的投递模式。 消息发送的时候,这个字段的值将被忽略。在消息被发送成功以后,这个属性将会持有发送方法里指定的值。 更多相关信息参见章节7.7“消息投递模式”。 JMSDeliveryMode 提供者发送消息时,JMSMessageID头字段的值是消息的唯一标识。 消息发送的时候,这个字段的值将被忽略。在发送方法返回以后,这个属性将会持有提供者指定的值。 JMSMessageID的值是一个字符串,在历史库作为标识消息的唯一键值。它的确切范围是由提供者定义的。对于连接了一组 消息路由的具体提供者实例,这个范围至少应该满足提供者实例上的所有消息。 所有的JMSMessageID必须以“ID:”作为前缀。不要求消息ID对于不同的提供者也是唯一的。 因为消息ID会影响到消息的大小,如果提示应用中消息ID不会被使用,则一些提供者可能会优化消息开销。 MessageProducer和JMSProducer都提供了setDisableMessageID方法,此方法允许用用提供一个禁用消息ID的提示。当应 用设置一个生产者禁用消息ID,也就是说此应用不依赖于它生产的消息的ID值。 如果某个消息提供者接受这个提示,那么这些消息ID值必须被设置为null;如果某个提供者忽略这个提示,那么消息ID值必 须被设置为正常的唯一值。 JMSMessageID JMSTimestamp头字段包含消息传递给提供者的时间戳。它不是实际发送的时间。由于事务或其他客户端消息排队等原因, 实际发送的时间可能会有延迟。 消息发送的时候,这个字段的值将被忽略。在发送方法返回以后,这个属性将会被设置一个时间值,这个值一般在发送方法 调用和方法返回的时间之间。这个值是一个Java正常的毫秒数时间格式。 因为时间戳会影响到消息的大小,如果提示应用中时间戳不会被使用,则一些提供者可能会优化消息开销。 MessageProducer和JMSProducer都提供了setDisableJMSTimestamp方法,此方法允许用用提供一个禁用时间戳的提示。 当应用设置一个生产者禁用时间戳,也就是说此应用不依赖于它生产的消息的时间戳。 如果某个消息提供者接受这个提示,那么这些时间戳值必须被设置为0;如果某个提供者忽略这个提示,那么时间戳值必须被 设置为正常的值。 JMSTimestamp 客户端可以使用JMSCorrelationID头字段关联一个消息到另一个消息。 客户端可以使用的JMSCorrelationID头字段与另一个连接一个消息。典型的用法是关联一个响应消息到它对应的请求消息。 JMSCorrelationID可以使用如下几种值: 一个提供程序特定的消息ID 应用程序特定的字符串 一个提供本地的byte []的值。 由于通过JMS提供者发送的每条消息都分配有一个消息ID值,所以可以很方便地通过消息ID来关联消息。所有的消息ID值必 须以“ID:”作为前缀。 在某些情况下,应用程序(由多个客户端组成的),需要使用应用特定的值关联消息。例如,一个应用程序可以使用 JMSCorrelationID的值引用一些外部信息。应用程序指定的值必须不能使用“ID:”的前缀;这个前缀是为提供者生成的消息ID 值保留的。 如果一个提供者支持相关ID(correlation ID)的原生概念,JMS客户端可能需要使用特定的JMSCorrelationID值,以满足那 些期望使用它的非JMS客户端。为了这个目的,我们可以为JMSCorrelationID使用一个byte []类型的值。没有原生的相关ID 值的JMS提供者不要求支持byte[]类型的JMSCorrelationID值1。使用byte []类型的JMSCorrelationID值是不可移植的。 注1:方法 setJMSCorrelationIDAsBytes()和getJMSCorrelationIDAsBytes()的实现可能抛出 java.lang.UnsupportedOperationException异常。 JMSCorrelationID JMSReplyTo头字段包含了一个由发送消息的客户端提供的Destination。它标识了返回的响应消息应该发送到哪个目的地。 伴随着一个空的JMSReplyTo值发送的消息可能会代表一些事件的通知或者是一些发送者认为有意义的数据。 伴随着一个空的JMSReplyTo值发送的消息则一般表示需要一个响应。响应是可以可选的;这完全取决于处理此消息的客户 端。 JMSReplyTo 如果客户端接收到一个JMSRedelivered标识的消息,这可能说明(但不保证)这个消息曾经已经被投递过但是没有被消费者 确认。在一般情况下,无论何时消息被重新投递,提供者都必须设定消息的JMSRedelivered值。如果该字段设置为true,则 表示该消息可能已经被投递过,消费的应用程序应该采取额外的预防措施,以防止消息的重复处理。更多信息参见章节 6.2.10“消息确认”。 此字段对发送没有意义,发送方法不指定这个字段的值。 JMS定义的消息属性JMSXDeliveryCount将被设置为一个特定的消息已经被递送的次数。更多信息参见章节 3.5.11“JMSXDeliveryCount”。 JMSRedelivered JMSType头字段包含当一个消息被发送由客户端提供的消息类型标识符。 一些JMS提供者使用包含消息定义的消息仓库。JMSType头字段可以引用在提供者消息仓库中的信息定义。 JMS没有定义一个标准的消息定义仓库,也没有定义它包含的消息定义的命名策略。 有些消息系统需要为每个应用程序创建消息类型定义,为每个消息指定其类型。为了与这样的JMS提供者协同工作,JMS客 户端应指定一个JMSType值,无论应用程序是否使用它。这样就确保了该字段对那些需要它的提供者来说,是被正确地设置 的。 为了保证可移植性,JMS客户端应该使用的JMSType符号值,可以在安装时进行配置的、当前提供者的仓库中所定义的值。 如果使用的是字符串文本的话,对某些JMS提供者来说,它们可能不是有效的类型名称。 JMSType 当一个消息被发送时,JMS提供者会通过发送方法添加的存活时间(time to live)与消息的发送时间(对事务性发送,发送 时间是客户端发送消息的时间,不是事务提交的时间)来计算消息的过期时间。它表示为一个长整型值的,以毫秒为单位 的,过期时间到1970年1月1日午夜的UTC标准时间的差值。 当send方法返回时,消息的JMSExpiration头属性包含该值。当一个消息被接收时,它的JMSExpiration头属性也包含这个相 同的值。 如果存活时间指定为0,则消息的JMSExpiration头字段设置为零,表明该消息不会过期。 当一个未投递消息到达过期时间,该消息应该被销毁。JMS没有定义消息过期的通知。 客户端不应该接收已过期的消息;但是JMS不保证这不会发生。 JMSExpiration JMSPriority头属性包含了消息的优先级。 消息发送的时候,这个字段的值将被忽略。在消息被发送成功以后,这个属性将会持有发送方法里指定的值。 JMS定义从0级到9级的十级优先级。此外,客户端应优先考虑0-4为正常优先级, 5-9为高优先级。 JMS不要求提供者严格实现消息的优先级顺序;但是,它应该尽最大努力优先于正常消息投递加急消息。 JMSPriority 下表列出了JMS支持的消息头属性,以及它们是由JMS提供者设置还是由客户端应用设置。 表格3-1 消息头字段的值 消息头字段 被谁设置 Setter方法 JMSDestination JMS提供者发送方法 setJMSDestination (非客户端使用) JMSDeliveryMode JMS提供者发送方法 setJMSDeliveryMode(非客户端使用) JMSExpiration JMS提供者发送方法 setJMSExpiration(非客户端使用) JMSDeliveryTime JMS提供者发送方法 setJMSDeliveryTime(非客户端使用) JMSPriority JMS提供者发送方法 setJMSPriority(非客户端使用) JMSMessageID JMS提供者发送方法 setJMSMessageID(非客户端使用) JMSTimestamp JMS提供者发送方法 setJMSTimestamp(非客户端使用) JMSCorrelationID 客户端应用 setJMSCorrelationID, setJMSCorrelationIDAsBytes JMSReplyTo 客户端应用 setJMSReplyTo JMSType 客户端应用 setJMSType JMSRedelivered JMS提供者在投递之前 setJMSRedelivered(非客户端使用) 如何设置消息头的值 JMS允许管理员配置JMS覆盖客户端指定的值,包括投递模式、优先、存活时间和延迟投递时间。如果要做到这 样,JMSDeliveryMode、JMSPriority、JMSExpiration和JMSDeliveryTime头字段的值必须能够反映管理员指定的值。 JMS未明确定义管理员如何覆盖这些头字段的值。JMS提供者不是必须要支持此管理选项。 覆盖消息头属性 当一个消息被发送时,JMS提供者会通过发送方法添加的延迟投递时间(delivery delay)与消息的发送时间(对事务性发 送,发送时间是客户端发送消息的时间,不是事务提交的时间)来计算消息的投递时间。它表示为一个长整型值的,以毫秒 为单位的,过期时间到1970年1月1日午夜的UTC标准时间的差值。 当send方法返回时,消息的JMSDeliveryTime头属性包含该值。当一个消息被接收时,它的JMSDeliveryTime头属性也包含 这个相同的值。 一个消息的投递时间是提供者使得这个消息对于目标目的地可见和消费者投递可用的最早时间。 在一个消息的投递时间到达之前,客户端无法接收此消息。 JMSDeliveryTime 除了标准的消息头字段,消息接口还包含了一种支持属性值的内建机制。实际上,这为消息提供了一种添加可选的消息头字 段的机制。 消息属性允许客户端通过消息选择器(参见章节3.8“消息选择”),使用应用相关的标准,在JMS提供者端选择消息。 消息属性 属性的名称必须符合消息选择器标识的规则。更多信息参见章节3.8“消息选择”。 属性名称 属性值可以是如下类型:boolean、byte、short、int、long、float、double和String。 属性值 属性值在发送消息之前设置。当客户端接收一个消息后,消息属性都是只读模式的。如果客户端想在这时设置属性值,将会 抛出一个MessageNotWriteable Exception异常。 一个属性值在消息体内可能会重复,也可能不会。尽管JMS没有定义一个策略来说明应该使用什么来构建一个属性,应用开 发者应该要注意到,一般来说,对JMS提供者处理消息体里的数据比消息属性里的数据要有效得多。 为了最好的性能,应用只应该在需要自定义消息头的时候使用消息属性。这么做的主要理由是用于支持自定义消息选择。 更多JMS消息属性的信息参见章节3.8“消息选择”。 使用属性 属性转换支持见下面表格。其中标记为X的场景即为支持的转换,未标记的场景必须抛出MessageFormatException异常。字 符串到数值类型的转换,如果数值类型的valueOf方法不能将这个字符串作为合法的格式接受,那么则必须抛出 java.lang.NumberFormatException异常。想要读取一个null值作为Java基本类型,必须要作为基本类型相应的 valueOf(String)转换方法调用一个null值参数来处理。 每行表示的类型可以被当做列所在的类型来读取。 表格3-2 属性值转换 boolean byte short int long float double String boolean X X byte X X X X X short X X X X int X X X long X X float X X X double X X String X X X X X X X X 属性值转换 除了类型相关的属性set/get方法,JMS还提供了setObjectProperty/getObject Property方法。这就支持相同的一组属性类 型,它们对原生数值类型使用对象化的类型封装。这样就使得属性类型的决定时间由编译时变成了运行时。他们支持相同的 属性值转换。 方法setObjectProperty接受Boolean、Byte、Short、Integer、Long、Float、Double和String类型。如果试图使用其他类 型,则会抛出JMS MessageFormatException异常。 方法getObjectProperty只会返回如下几种值:null,Boolean、Byte、Short、Integer、Long、Float、Double和String类型 的值。如果指定名称的属性不存在,则会返回一个null值。 属性转为对象 属性值的顺序在本规范中没有定义。为了迭代消息里的所有属性性质,可以使用getPropertyNames方法获取属性名称枚举 器,然后使用每个属性的get方法拿到对应的值。 方法getPropertyNames不会返回JMS标准头字段。 属性迭代 可以使用clearProperties方法删除一个消息的所有属性。此时这个消息的属性是一个空集合。新的属性实体可以创建和添加 到这个消息。 清除一个消息的所有属性实体时不会清除它的消息体。 JMS不提供删除单个消息属性的方法。 清除消息属性值 获取一个没有被设置的属性的值,跟获取一个存在但是设置了null值的属性,效果是一样的。 不存在的属性 JMS reserves the 'JMSX' property name prefix for JMS defined properties. The full set of these properties is provided in Table 3-3. This table defines: • The name of the property • The type of the property (integer or string) • Whether support for the property is mandatory or optional. • Whether the property is set by the sending client, by the provider when the message is sent, or by the provider when the message is received. • The purpose of the property Table 3-3 JMS defined properties Name Type Optional or mandatory Set By Use JMSXUserID String Optional Provider on Send The identity of the user sending the message JMSXAppID String Optional Provider on Send The identity of the application sending the message JMSXDeliveryCount int Mandatory Provider on Receive The number of message delivery attempts. See section 3.5.11 “JMSXDeliveryCount”. JMSXGroupID String Optional Client The identity of the message group this message is part of JMSXGroupSeq int Optional Client The sequence number of this message within the group; the first message is 1, the second 2,... JMSXProducerTXID String Optional Provider on Send The transaction identifier of the transaction within which this message was produced JMSXConsumerTXID String Optional Provider on Receive The transaction identifier of the transaction within which this message was consumed JMSXRcvTimestamp long Optional Provider on Receive The time JMS delivered the message to the consumer JMSXState int Optional Provider Assume there exists a message warehouse that contains a separate copy of each message sent to each consumer and that these copies exist from the time the original message was sent. Each copy’s state is one of: 1(waiting), 2(ready), 3(expired) or 4(retained) Since state is of no interest to producers and consumers it is not provided to either. It is only of relevance to messages looked up in a warehouse and JMS provides no API for this. New JMS defined properties may be added in later versions of JMS. The Enumeration ConnectionMetaData.getJMSXPropertyNames() method returns the names of the JMSX properties supported by a connection. JMSX properties may be referenced in message selectors whether or not they are supported by a connection. If they are not present in a message, they are treated like any other absent property. The effect of setting a message selector on a property which is set by the provider on receive is undefined. The existence, in a particular message, of optional JMS defined properties that are set by a JMS Provider depends on how a particular provider controls use of the property. It may choose to include them in some messages and omit them in others depending on administrative or other criteria. JMSX properties ‘set by provider on send’ are available to both the producer and the consumers of the message. JSMX properties set by the provider on receive are only available to the consumers. JMSXGroupID and JMSXGroupSeq are standard properties clients should use if they want to group messages. All providers must support them. The case of these JMSX property names must be as defined in the table above. Unless specifically noted, the values and semantics of the JMSX properties are undefined. 新的JMS定义的属性可能会在以后的版本中的JMS加入。 枚举ConnectionMetaData.getJMSXPropertyNames()方法返回 一个连接所支持的JMSX属性的名称。 JMSX属性可能在消息选择引用不论他们是由一个连接的支持。如果它们不存在于一个 消息,他们像对待其他任何缺席的财产。在其上通过在接收的提供者设置一个属性设置消息选择器的作用是不确定的。 的存 在,一个特定的消息中,可选的JMS是由一个JMS提供者设置定义的属性依赖于一个特定的供应商控制如何使用该物业。它 可能会选择将它们包括在一些消息并忽略他们在其他人根据行政或其他标准。 JMSX性质“由供应商对发送设置'可兼顾生产者 和消息的消费者。只提供给消费者JSMX性质由提供者在收到设置。 JMSXGroupID和了JMSXGroupSeq是标准属性的客户 端应该使用,如果他们想组消息。所有供应商必须支持他们。 这些JMSX属性名称的情况下,必须在以上表格来定义。 除非 特别说明,本JMSX属性值和语义是不确定的。 JMS定义的属性 JMS保留“JMS_”属性名前缀用于提供者相关的属性。每个提供者定义自己的值。JMS提供者使用的这种机制使得每个消息对 于其JMS客户端都是特殊的。 提供者相关的属性的目的是为了提供需要JMS与提供者相关的原生客户端一起使用的特殊功能。这些客户端一般不会使用 JMS到JMS的消息处理。 提供者相关的属性 当客户端接收到一个消息时,一个JMS定义的强制性的消息属性JMSXDelivery Count将被设置,这个属性记录了消息被投递 的次数。在第一次接收到一个消息时,它会被设置为1,所以2以上的值表示该消息已被投递过。 如果JMSRedelivered消息头的值被设置,那么JMSXDeliveryCount属性值必须是2以上。更多JMSRedelivered消息头的信 息请参见章节3.4.7“JMSRedelivered”。 JMSXDeliveryCount属性的目的是允许消费的应用程序判断一个消息是否被重复投递过,以便采取适当的处理。 JMSXDeliveryCount属性的值不能保证是完全正确的。JMS提供者一般不会持久化这个值来确保此状态不会因为故障而丢 失。 JMSXDeliveryCount 所有的JMS消息都支持指定的客户端上JMS消费者的显示确认消息的确认方法。 如果一个客户端使用自动确认模式,那么对确认方法的调用将被忽略。 更多信息参见章节6.2.10“消息确认”。 消息确认 Message接口是所有消息的根接口。它为所有的消息定义了使用的消息头字段、属性功能,以及确认方法。 消息接口 许多消息传递应用程序需要过滤和分类,他们产生的消息。 在将消息发送到一个接收器的情况下,这可以以合理的效率通过把标准的消息中,并具有接收客户端丢弃那些它不感兴趣做 当一个消息被广播到多个客户端,它放置到标准的消息头,以便它是可见的JMS提供者变得非常有用。这允许提供者来处理 多,否则将需要由应用程序进行的过滤和路由的工作。 JMS提供了一个工具,允许客户端消息选择委托给他们的JMS提供者。这简化了客户端的工作,并允许JMS提供者以消除时 间和带宽他们原本浪费将消息发送到不需要他们的客户。 客户端安装应用程序特定的选择标准来使用消息属性的消息。客户端使用JMS消息选择器表达式指定消息的选择标准。 Many messaging applications need to filter and categorize the messages they produce. In the case where a message is sent to a single receiver, this can be done with reasonable efficiency by putting the criteria in the message and having the receiving client discard the ones it’s not interested in. When a message is broadcast to many clients, it becomes useful to place the criteria into the message header so that it is visible to the JMS provider. This allows the provider to handle much of the filtering and routing work that would otherwise need to be done by the application. JMS provides a facility that allows clients to delegate message selection to their JMS provider. This simplifies the work of the client and allows JMS providers to eliminate the time and bandwidth they would otherwise waste sending messages to clients that don’t need them. Clients attach application-specific selection criteria to messages using message properties. Clients specify message selection criteria using JMS message selector expressions. 消息选择 A JMS message selector allows a client to specify, by message header, the messages it’s interested in. Only messages whose headers and properties match the selector are delivered. The semantics of not delivered differ a bit depending on the MessageConsumer being used. See section 4.1.2 “Queue semantics” and 4.2.2 “Topic semantics” for more details. Message selectors cannot reference message body values. A message selector matches a message when the selector evaluates to true when the message’s header field and property values are substituted for their corresponding identifiers in the selector. JMS消息选择器允许客户端指定,由消息头,它感兴趣的头和属性相匹配的选择器只传递消息的消息。未交付的语义差别有 点视的MessageConsumer被使用。请参见4.1.2节“队列语义”和4.2.2“主题语义”的更多细节。 消息选择器不能引用消息体 值。 消息选择当选择计算结果为true时,消息的头字段和属性值的选择取代其相应的标识符匹配的消息。 消息选择器 A message selector is a String whose syntax is based on a subset of the SQL922 conditional expression syntax. 2 See X/Open CAE Specification Data Management: Structured Query Language (SQL), Version 2, ISBN: 1-85912-151-9 March 1996. If the value of a message selector is an empty string, the value is treated as a null and indicates that there is no message selector for the message consumer. The order of evaluation of a message selector is from left to right within precedence level. Parentheses can be used to change this order. Predefined selector literals and operator names are written here in upper case; however, they are case insensitive. A selector can contain: • Literals: A string literal is enclosed in single quotes, with an included single quote represented by doubled single quote; for example, 'literal' and 'literal''s'. Like Java String literals, these use the Unicode character encoding. An exact numeric literal is a numeric value without a decimal point, such as 57, -957, +62; numbers in the range of Java long are supported. Exact numeric literals use the Java integer literal syntax. An approximate numeric literal is a numeric value in scientific notation, such as 7E3 and -57.9E2, or a numeric value with a decimal, such as 7., -95.7, and +6.2; numbers in the range of Java double are supported. Approximate literals use the Java floating-point literal syntax. The boolean literals TRUE and FALSE. • Identifiers: An identifier is an unlimited-length character sequence that must begin with a Java identifier start character; all following characters must be Java identifier part characters. An identifier start character is any character for which the method Character.isJavaIdentifierStart returns true. This includes '' and '$'. An identifier part character is any character for which the method Character.isJavaIdentifierPart returns true. Identifiers cannot be the names NULL, TRUE, or FALSE. Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or ESCAPE. Identifiers are either header field references or property references. The type of a property value in a message selector corresponds to the type used to set the property. If a property that does not exist in a message is referenced, its value is NULL. The semantics of evaluating NULL values in a selector are described in Section 3.8.1.2 “Null values”. The conversions that apply to the get methods for properties do not apply when a property is used in a message selector expression. For example, suppose you set a property as a string value, as in the following: myMessage.setStringProperty("NumberOfOrders", "2"); The following expression in a message selector would evaluate to false, because a string cannot be used in an arithmetic expression: "NumberOfOrders > 1" Identifiers are case sensitive. Message header field references are restricted to JMSDeliveryMode, JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be null and if so are treated as a NULL value. Any name beginning with 'JMSX' is a JMS defined property name. Any name beginning with 'JMS' is a provider-specific property name. Any name that does not begin with 'JMS' is an application-specific property name. • Whitespace is the same as that defined for Java: space, horizontal tab, form feed and line terminator. • Expressions: A selector is a conditional expression; a selector that evaluates to true matches; a selector that evaluates to false or unknown does not match. Arithmetic expressions are composed of themselves, arithmetic operations, identifiers with numeric values, and numeric literals. Conditional expressions are composed of themselves, comparison operations, logical operations, identifiers with boolean values, and boolean literals. • Standard bracketing () for ordering expression evaluation is supported. • Logical operators in precedence order: NOT, AND, OR • Comparison operators: =, >, >=, <, <=, <> (not equal) Only like type values can be compared. One exception is that it is valid to compare exact numeric values and approximate numeric values (the type conversion required is defined by the rules of Java numeric promotion). If the comparison of non-like type values is attempted, the value of the operation is false. If either of the type values evaluates to NULL, the value of the expression is unknown. String and Boolean comparison is restricted to = and <>. Two strings are equal if and only if they contain the same sequence of characters. • Arithmetic operators in precedence order: +, - (unary) *, / (multiplication and division) +, - (addition and subtraction) Arithmetic operations must use Java numeric promotion. arithmetic-expr1 [NOT] BETWEEN arithmetic-expr2 and arithmetic-expr3 (comparison operator) "age BETWEEN 15 AND 19" is equivalent to "age >= 15 AND age <= 19" "age NOT BETWEEN 15 AND 19" is equivalent to "age < 15 OR age > 19" • identifier [NOT] IN (string-literal1, string-literal2,...) (comparison operator where identifier has a String or NULL value). "Country IN ('UK', 'US', 'France')" is true for 'UK' and false for 'Peru'; it is equivalent to the expression (Country = 'UK') OR (Country = 'US') OR (Country = 'France') Country NOT IN ('UK', 'US', 'France') is false for 'UK' and true for 'Peru'; it is equivalent to the expression "NOT ((Country = 'UK') OR (Country = 'US') OR (Country = 'France'))" If identifier of an IN or NOT IN operation is NULL, the value of the operation is unknown. • identifier [NOT] LIKE pattern-value [ESCAPE escape-character] (comparison operator, where identifier has a String value; pattern-value is a string literal where '' stands for any single character; '%' stands for any sequence of characters, including the empty sequence, and all other characters stand for themselves. The optional escape-character is a single-character string literal whose character is used to escape the special meaning of the '' and '%' in pattern-value.) "phone LIKE '12%3'" is true for '123' or '12993' and false for '1234' "word LIKE 'lse'" is true for 'lose' and false for 'loose' "underscored LIKE '\%' ESCAPE '\'" is true for '_foo' and false for 'bar' "phone NOT LIKE '12%3'" is false for '123' and '12993' and true for '1234' If identifier of a LIKE 消息选择器语法 or NOT LIKE operation is NULL, the value of the operation is unknown. • identifier IS NULL (comparison operator that tests for a null header field value or a missing property value) "prop_name IS NULL" • identifier IS NOT NULL (comparison operator that tests for the existence of a non-null header field value or property value) "prop_name IS NOT NULL" JMS providers are required to verify the syntactic correctness of a message selector at the time it is presented. A method providing a syntactically incorrect selector must result in a JMS InvalidSelectorException. JMS providers may also optionally provide some semantic checking at the time the selector is presented. Not all semantic checking can be performed at the time a message selector is presented, because property types are not known. The following message selector selects messages with a message type of car and color of blue and weight greater than 2500 lbs: "JMSType = 'car' AND color = 'blue' AND weight > 2500" As noted above, header fields and property values may be NULL. The evaluation of selector expressions containing NULL values is defined by SQL 92 NULL semantics. A brief description of these semantics is provided here. SQL treats a NULL value as unknown. Comparison or arithmetic with an unknown value always yields an unknown value. The IS NULL and IS NOT NULL operators convert an unknown header or property value into the respective TRUE and FALSE values. The boolean operators use three-valued logic as defined by the following tables: Table 3-4 The definition of the AND operator AND T F U T T F U F F F F U U F U Null值 When used in a message selector JMSDeliveryMode is treated as having the values 'PERSISTENT' and 'NON_PERSISTENT'. Date and time values should use the standard Java long millisecond value. When a date or time literal is included in a message selector, it should be an integer literal for a millisecond value. The standard way to produce millisecond values is to use java.util.Calendar. Although SQL supports fixed decimal comparison and arithmetic, JMS message selectors do not. This is the reason for restricting exact numeric literals to those without a decimal (and the addition of numerics with a decimal as an alternate representation for approximate numeric values). SQL comments are not supported. 当在消息选择使用JMSDeliveryMode被视为具有价值“持久性”和“NON_PERSISTENT”。 日期和时间值应该使用标准的Java长毫秒值。当日期或时间文字包含在消息选择器,它应该是一个整数文字的毫秒值。生产 毫秒值的标准方法是使用java.util.Calendar中。 虽然SQL支持固定小数比较和运算,JMS消息选择不要。这是制约精确数字的原因文字,那些没有小数点(并增加数值计算 与小数为近似数值的另一种表示)。 不支持SQL注释。 特别注意 发送消息后,客户端可保留和修改,而不会影响到已发送邮件。相同的消息对象可以多次发送。 在它的发送方法的执行,决不能由客户端进行修改的消息。如果被修改,发送的结果是不确定的。 After sending a message, a client may retain and modify it without affecting the message that has been sent. The same message object may be sent multiple times. During the execution of its sending method, the message must not be changed by the client. If it is modified, the result of the send is undefined. 访问发送的消息 当接收到消息时,它的报头字段值是可以改变的;然而,它的属性条目和它的身体是只读的,按照本章的规定。 对于只读的限制的理由是,它给JMS提供程序在如何实现收到的邮件管理更自由。例如,他们可能会返回一个引用驻留在一 个内部消息缓冲区而不是被迫进行复印属性条目和身体值的报文对象。 消费者可以在调用任一clearBody或clearProperties方法,使身体或财产写入修改后收到的消息。如果消费者修改收到的消 息,该消息随后被交还,交还该消息必须是原始的,未经修改的消息(除了头和属性由JMS提供者作为交还,如 JMSRedelivered头的结果,修改和JMSXDeliveryCount属性)。 When a message is received, its header field values can be changed; however, its property entries and its body are read- only, as specified in this chapter. The rationale for the read-only restriction is that it gives JMS Providers more freedom in how they implement the management of received messages. For instance, they may return a message object that references property entries and body values that reside in an internal message buffer rather than being forced to make a copy. A consumer can modify a received message after calling either the clearBody or clearProperties method to make the body or properties writable. If the consumer modifies a received message, and the message is subsequently redelivered, the redelivered message must be the original, unmodified message (except for headers and properties modified by the JMS provider as a result of the redelivery, such as the JMSRedelivered header and the JMSXDeliveryCount property). 修改接收的消息的值 JMS provides five forms of message body. Each form is defined by a message interface: • StreamMessage - a message whose body contains a stream of Java primitive values. It is filled and read sequentially. • MapMessage - a message whose body contains a set of name-value pairs where names are String objects and values are Java primitive types. The entries can be accessed sequentially by enumerator or randomly by name. The order of the entries is undefined. • TextMessage - a message whose body contains a java.lang.String. The inclusion of this message type is based on our presumption that String messages will be used extensively. One reason for this is that XML will likely become a popular mechanism for representing the content of JMS messages. • ObjectMessage - a message that contains a serializable Java object. If a collection of Java objects is needed, one of the collection classes provided in JDK 1.2 can be used. • BytesMessage - a message that contains a stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format. In many cases, it will be possible to use one of 44 Java Message Service Version 2.0 the other, self-defining, message types instead. Although JMS allows the use of message properties with byte messages it is typically not done since the inclusion of properties may affect the format. 3.11.1. Clearing a message body The clearBody method of Message resets the value of the message body to the ‘empty’ initial message value as set by the message type’s create method provided by Session. Clearing a message’s body does not clear its property entries. 3.11.2. Read-only message body When a message is received, its body is read only. If an attempt is made to change the body a MessageNotWriteableException must be thrown. If its body is subsequently cleared, the body is in the same state as an empty body in a newly created message. 3.11.3. Conversions provided by StreamMessage and MapMessage Both StreamMessage and MapMessage support the same set of primitive data types. The types can be read or written explicitly using methods for each type. They may also be read or written generically as objects. For instance, a call to MapMessage.setInt("foo", 6) is equivalent to MapMessage.setObject("foo", new Integer(6)). Both forms are provided because the explicit form is convenient for static programming and the object form is needed when types are not known at compile time. Both StreamMessage and MapMessage support the following conversion table. The marked cases must be supported. The unmarked cases must throw a JMS MessageFormatException. The String to numeric conversions must throw a java.lang.NumberFormatException if the numeric’s valueOf() method does not accept the String value as a valid representation. StreamMessage and MapMessage must implement the String to boolean conversion as specified by the valueOf(String) method of Boolean as defined by the Java language. Attempting to read a null value as a Java primitive type must be treated as calling the primitive’s corresponding valueOf(String) conversion method with a null value. Since char does not support a String conversion, attempting to read a null value as a char must throw NullPointerException. Getting a MapMessage field for a field name that has not been set is handled as if the field exists with a null value. If a read method of StreamMessage or BytesMessage throws a MessageFormatException or NumberFormatException, the current position of the read pointer must not be incremented. A subsequent read must be capable of recovering from the exception by rereading the data as a different type. A value written as the row type can be read as the column type Table 3-7 Conversions for StreamMessage and MapMessage boolean byte short char int long float double String byte[] JMS消息体 JMS提供了一组定义JMS消息模型基于消息的接口。它不提供这些接口的实现。 每个JMS提供者提供它自己的实现它的Session的消息创建方法。这使得供应商使用都适合其需求的信息实现。 提供者必须准备接受来自客户端,消息的实现是不是它自己的。与“外部”执行情况的消息可能不会为有效地处理作为一个供 应商自身的执行情况;但是,它必须被处理。 46 Java消息服务2.0版 JMS消息接口提供写/ set方法在消息体和消息属性设置对象的值。所有这些方法都必须实现自己的输入对象复制到该消息。 输入对象的值允许为空,访问时将返回null。一个例外是,BytesMessage不支持空流的概念,并试图写入一个空进入它必须 抛出java.lang.NullPointerException。 JMS消息接口提供读/得到一个消息体和消息属性访问对象的方法。所有这些方法都必须实现返回访问的消息对象的一个副 本。 JMS provides a set of message interfaces that define the JMS message model. It does not provide implementations of these interfaces. Each JMS provider provides its own implementation of its Session’s message creation methods. This allows a provider to use message implementations that are tailored to its needs. A provider must be prepared to accept, from a client, a message whose implementation is not one of its own. A message with a ‘foreign’ implementation may not be handled as efficiently as a provider’s own implementation; however, it must be handled. 46 Java Message Service Version 2.0 The JMS message interfaces provide write/set methods for setting object values in a message body and message properties. All of these methods must be implemented to copy their input objects into the message. The value of an input object is allowed to be null and will return null when accessed. One exception to this is that BytesMessage does not support the concept of a null stream and attempting to write a null into it must throw java.lang.NullPointerException. The JMS message interfaces provide read/get methods for accessing objects in a message body and message properties. All of these methods must be implemented to return a copy of the accessed message objects. JMS消息接口的提供者实现 messaging domains 受管对象 JMS受管对象是那些包含JMS配置信息的对象,这些配置信息由JMS管理员创建,然后由客户端使用。它们让管理企业中的 JMS应用变得具有可操行性。 虽然受管对象的接口不显式地依赖JNDI,但是JMS约定JMS客户端是通过使用JNDI在命名空间中查找而发现受管对象的。 管理员可以将受管对象放到命名空间的任何位置。JMS没有定义命名策略。 这种将JMS和管理区分开来的策略有几个好处: 它对客户端隐藏了提供者特有的配置细节。 它将JMS的管理信息抽象成容易被通用管理控制台组织和管理的Java对象。 由于JNDI提供者会提供所有流行的命名服务,所以也就意味着JMS提供者提供受管对象的一个实现就可以在任何地方运 行了。 受管对象不应该持有任何远程资源。它的查找不应该使用远程资源,除了那些JNDI自身使用的资源以外。 客户端应当把受管对象看作是本地Java对象。查找它们不应该有任何隐藏的副作用或意料之外的大量本地资源使用。 JMS定义了两类受管对象:Destination和ConnectionFactory。 JMS期望提供者为管理员提供在JNDI命名空间里创建和配置受管对象的工具。JMS提供者提供的受管对象的实现应该同时是 javax.naming.Referenceable和java.io.Serializable 的,以便它们能够被存储在所有的JNDI命名上下文中。另外,JMS建议 这些实现遵循JavaBean设计模式。 概述 JMS没有定义一个标准的地址语法。尽管考虑到了,但是现存企业消息产品间的地址差异是如此之大,以至于寻求一个单一 的语法是不可能的。因此JMS定义了Destination 对象来封装提供者特定的地址作为替代方案。 由于Destination是一个受管对象,因此除了包含地址外,它还可能包含其他的提供者特定的配置信息。 Destination对象支持并发使用。 JMS同时也支持客户端使用提供者特定的地址名称。更多信息参见章节6.2.3“创建Destination对象”。 目的地(Destination) 连接工厂封装了一系列由管理员定义的连接配置参数。客户端使用它来创建和JMS提供者之间的连接。 传统API使用ConnectionFactory类型的连接工厂。 简化API使用ConnectionFactory类型的连接工厂。 点对点消息域API使用QueueConnectionFactory类型的连接工厂。 发布订阅消息域API使用TopicConnectionFactory类型的连接工厂。 连接工厂对象支持并发使用。 如何使用连接工厂创建连接参见章节 6.1“Connections”。 连接工厂(ConnectionFactory) connecting to provider send messages receive messages other facilities exceptions application server facilities use in java ee resource adapter classic examples simplified examples change history
还剩91页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 12 人已下载

下载pdf

pdf贡献者

gbp8

贡献于2014-12-08

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf