用JMS编程.pdf
2358 用用JMS编程编程 在本章中,我们将讨论 Java 消息发送服务(JMS)接口概念和 MQSeries 实施,以及如何使用 JMS 编程。我们将在消息发送编程模式的上下文中探讨 JMS 概念。2368.1 什么是什么是JMS?与 JDBC API for databases 一样,Java Message Services(JMS)是消息发送的标准 API。JMS 规范(1.0.2)由 Sun Microsystems 开发,IBM 和其他企业消息发送销售商、事务处理销售商以及 RDBMS 销售商都积极参与了开发过程。JMS 为 Java 程序与对消息发送系统对象进行各种操作的消息发送系统进行互动提供了一个常见的模型。程序对消息发送系统对象进行的常见操作包括创建消息、发送消息、接收消息以及从企业消息发送系统中读取消息。JMS 为那些用 Java 开发的程序提供了一种访问这些消息发送系统操作的常见方法。JMS 具有两种消息发送风格,或者说它具有两个域:?一对一或点到点模型;?发布预订模型。JMS 仅仅是种规范。每个企业消息发送系统销售商都必须就其特定的消息发送系统提供实施规范的类。在本章中,我们将描述 JMS API 的 MQSeries 实施、讨论 JMS API 概念和 MQSeries 的JMS 实施能力,并讲解在可以利用 MQSeries JMS 实施的不同情境中如何利用 MQSeries JMS。为什么要使用为什么要使用 JMS?JMS 标准非常重要,其原因在于:?它是第一个获取广泛跨行业支持的企业消息发送 API;?它提供的标准消息发送概念和惯例适用于广泛的企业消息发送系统,因而简化了企业应用程序的开发;?它可以利用现有的、企业证明成功可行的消息发送系统;?它添加了完全用现有非 JMS 客户机解释的新 JMS 客户机,从而允许您扩展现有的基于消息的应用程序;?它允许您可以编写便携性强的基于消息的商业应用程序。2378.2 概述概述 JMS 是定义 JMS 客户机如何访问企业消息发送产品功能的一系列接口和相关语义。我们这里所描述的消息是指企业应用程序所使用的异步请求、报表或事件。它们既包含协同这些系统所需的重要信息;又包含着描述特定商业行为的精确格式化的数据。通过这些消息的交流,每个应用程序都能跟踪企业的发展。JMS 定义了一系列常见的企业消息发送概念和功能。它最大限度地减少了 Java 语言程序设计人员在使用企业消息发送产品前必须学会的概念集。也最大限度地加强了消息发送应用程序的便携性。JMS 标准虽然提供了独立于不同销售商的编程接口,但是并不定义出通讯协议。JMS 模型模型 JMS 定义了消息传递服务的一般视图。理解该视图,并弄清它是如何映射到底层的MQSeries 传输上的,相当重要。一般 JMS 模型是建立在 Sun 的 javax.jms 包所定义的接口上的,请见图 81。238 图81 JMS模型 连接连接 连接提供了到底层传输的访问,并被用来创建会话。在 MQSeries 上下文中,连接提供了储存参数,如队列管理器名、远程主机名(在 Java 客户连接性中)等的地方。换言之,MQSeries JMS连接一般都在Java虚拟机之外分配MQSeries资源。连接也支持同时使用。连接可以提供以下好处:?包括与 JMS 供应方的开放式连接。它通常代表客户机和供应方服务端口之间的一个开放的 TCPIP 槽;?它的创建就是客户机认证发生之处;?它可以指定唯一的客户机标识符;239?它提供 ConnectionMetaData;?它支持可选的 ExceptionListener。由于建立连接时完成了认证和通讯设置,因此连接相对来说是个重量级的 JMS 对象。大多数客户机都使用单一的连接进行消息发送。其他更先进的应用程序可能会使用几个连接。JMS 并不为使用多个连接而设计原因;但是,这样做可能有操作上的原因。JMS 客户机一般创建一个连接、一个或多个会话以及许多消息生成器和使用者。当创建连接时,它处在停止模式,这就是说没有消息再被送达。重点:重点:连接是在停止模式中创建的。通常,直到设置完成前,连接都处在停止模式中。在完成时,将调用连接的 start()方法,而消息则开始到达连接的使用者。此设置惯例可以在客户机仍在进行设置过程中尽可能减少异步消息送达所带来的任何客户机混乱。连接可以立即启动,而设置可在随后进行。这样做的客户机必须在设置过程中就准备好处理异步消息送达。提示:提示:消息生成器可以在停止连接时发送消息。不是直接创建连接的,而是利用连接库建立的。库对象可以储存在 JNDI 名称空间中,从而将 JMS 应用程序与供应方特定信息隔离开来。连接库对象是利用 MQSeries JMS 管理工具 JMSAdmin 创建的。该工具使得管理员可以给 JNDI 名称空间定义 MQSeries JMS对象的 8 种类型。请参见第 8.4.9 节 利用JMSAdmin以VisualAge for Java管理JMS JNDI对象(见本书第 260 页)。创建连接创建连接 客户机利用连接库来创建连接。要使用何种连接库类型取决于您想要哪种类型的连接:?就 PTP 连接而言,我们利用 QueueConnectionFactory 或 XAQueueConnectionFactory来获取 QueueConnection 或 XAQueueConnection;240?就 发 布 预 订 消 息 发 送 模 式 而 言,我 们 利 用 TopicConnectionFactory 或XATopicConnectionFactory 来获取 TopicConnection 或 XATopicConnection。为了创建连接,我们应当进行以工作:?从 JNDI 名称空间接收库对象 JNDI API 向以 Java 编写的应用程序提供了命名和目录功能。它是利用 Java 的对象模型专门为 Java 设计的。利用 JNDI,Java 应用程序可以储存并接收任何类型的命名为 Java 的对象。另外,JNDI 提供进行标准目录操作的方法,如将属性与对象相关联并利用对象属性查找对象等。在此常见的 API 之后,可以无缝地插入不同的命名和目录服务供应方。这使得 Java应用程序可以通过各种各样的命名和目录服务来利用信息,如 LDAP、NDS、DNS和 NIS(YP)等,也使得 Java 应用程序可以与传统应用程序和系统并存。在 JNDI 中,所有的命名和目录操作都是根据上下文进行的。没有绝对的根。因此,JNDI 定义了初始上下文,它是命名和目录操作名解析的起始点。一旦有了初始上下文,您就可以利用它来查看其他上下文和对象。?为了从 JNDI 名称空间接收对象,必须按照下面这段代码所显示的那样设置初始上下文:import javax.jms.*import javax.naming.*;import javax.naming.directory.*;java.util.Hashtable;Hashtable env new Hashtable();env.put(Context.INITIAL_CCONTEXT_FACTORY,icf);env.put(Context.PROVIDER_URL,url);Context ctx new InitialDirContext(env);Icf 为初始上下文定义了库类,url 则定义了随上下文而变的 URL。?一旦获取了初始上下文,我们就可以利用 lookup()方法来从名称空间接收对象。下面这段代码从基于 LDAP 的名称空间接收 QueueConnectionFactory 名 firstQCF;QueueConnectionFactory qFactory;queueFactory(QueueConnectionFactory)ctx.lookup(“cnfirstQCF”);?利用库对象来获取连接。241利用库对象的 createQueueConnection()方法来创建连接,请参见如下的例子:QueueConnection connection;connection qFactory.createQueueConnection();?启动连接 JMS 规范定义指出,应当在“停止”状态下创建连接。在您可以利用连接发送消息之前,必须显式启动连接。我们利用 start()方法启动连接,请参见如下的例子:connection.start();会话会话 为生成和使用消息提供上下文,包括用来创建消息生成器和消息使用者的方法。JMS 会话是生成和使用消息的单线程上下文。尽管它可以在 Java 虚拟机之外分配供应方资源,但我们还是将其看作轻量级 JMS 对象。我们可以分别利用连接对象的 createQueueSession()或 createTopicSession()方法来创建会话。创建会话方法包括两个参数:1.可决定会话是否进行事务处理的 boolean。在事务处理的会话中,全部发送、或者全部接收作为一个单位的一组消息。在非事务处理会话中,分别发送或接收消息。2.定义识别模式的参数。请参见如下的例子:session connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);这是用 AUTO_ACKNOWLEDGE 来创建非事务处理会话的最简单的情况。连接是线程安全的,但会话和由会话创建的对象不是线程安全的。我们建议多线程应用程序应当对每个线程都使用不同的会话。会话有以下几种用途:?它是消息生成器和使用者的库;?它提供了供应方优化的消息库;242?它既支持单一事务处理,又支持一系列将跨越生成器和使用者的库结合到原子单位的事务处理;?会话为它使用和生成的消息定义了连续序列;会话保存了它使用的消息,直到识别该消息;?会话串行化注册到消息使用者的消息侦听器。会话可以创建并服务于多个消息生成器和使用者。一种典型的用法就是在消息到达前一直在同步消息使用者上保持线程块。然后线程可以使用一个或更多的会话消息生成器。如果一个客户机希望在其他客户机使用消息时具备一个生成消息的线程,那么该客户机就应当为生成线程使用另外的会话。一旦启动了连接,任何具有侦听器或注册消息侦听器的会话就会被赋予送达消息的控制线程。客户机代码从另一个控制线程利用会话或任何构成会话的对象都是错误的。唯一的例外就是使用会话或连接关闭方法。大多数客户机将它们的库自然地分成会话应当是比较容易的。该模型允许客户机简单启动并随着并行操作需要的增加而逐渐增加消息线程的复杂度。关闭方法是当另一个线程正在执行某个其他会话方法时唯一可以调用的会话方法。我们可以选择地指定会话为事务处理会话。每个事务处理会话都支持单一系列的事务处理。每个事务处理会将一系列消息发送和一系列消息接收归组到原子库单元中。事实上,事务处理将会话的输入消息流和输出消息流组织到原子单位集中。当提交事务处理时,会确认输入的原子单位,同时发送与其相关联的输出原子单位。如果已经进行了事务处理回退,那么其发送的消息则被毁坏,会话的输入也被自动恢复。事务处理输入和输出单位的内容就是会话的当前事务处理中所生成和使用的那些消息。243我们可以利用会话的提交或回退方法完成事务处理。会话的当前事务处理的完成将自动开始下一个事务处理。其结果就是,事务处理会话总是具有一个当前事务处理,且其库就在当前事务处理中完成。消息生成器消息生成器 JMS 客户机利用消息生成器发送消息到特定的目的地。我们通过传递目的地到会话对象提供的创建消息生成器方法,从而创建消息生成器。在点到点消息发送中,这将是利用 QueueSession 对象上的 createSender 方法所创建的QueueSender。QueueSender 通常是为特定队列创建的,因此所有利用该发送器发送的消息都会被发送到同样的目的地。我们利用队列对象指定目的地。队列对象即可以在运行时间中创建,也可以在 JNDI 名称空间中构造和储存。请参见如下的例子:Queue ioQueue;ioQueue (Queue).ctx.lookup(qLookUp);sender session.createSender(ioQueue);在发布预订消息发送中,这将是在 TopicSession 对象上利用 createPublisher 方法创建的 TopicPublisher。通常,Topic 是在创建 TopicPublisher 时指定的。在这种情况下,尝试去使用方法,该方法为未确认的 TopicPublisher,将生成 UnsupportedOperationException。请参见如下的例子:Topic topic;topic (Topic)ctx.lookup(“cnfirst.topic”);TopicPublisher pub session.createPublisher(topic);客户机也可以选择不提供目的地而创建消息生成器。在这种情况下,目的地必须输入每个发送操作。这种风格的消息生成器一般用来根据请求的 replyTo 目的地向请求发送回复。客户机可以通过消息生成器为发送的消息指定默认的送达模式、优先级和使用期限。它也可以为每条消息指定送达模式、优先级和使用期限。244客户机可以为它发送的每条消息指定单位为毫秒的使用期限值。这个值定义了消息到期时间,也就是消息使用期限的和以及消息发送的 GMT 时间(对事务处理发送而言,这是指客户机发送消息的时间而不是提交事务处理的时间)。发送消息发送消息 消息是用消息生成器发送的。因此在点到点(PTP)模型中发送消息时,您应当使用QueueSender 对象,而在发布预订模型中,您则应当使用 TopicPublisher 对象。在 PTP 模型中,应使用 QueueSender 的 send()方法发送消息。请参见如下的例子:outmessage session.createTextMessage();outmessage.setText(“Sample Message“);sender.send(outMessage);在发布预订模型中,应使用 TopicPublisher 对象的发布方法来发布消息。请参见如下的例子:pub.publish(outMessage);消息使用者消息使用者 消息使用者是用来接收消息的。MessageConsumer 接口是所有消息使用者的父级接口。在 PTP 模型中,这将是 QueueReceiver。在发布预订模型中,这将是 TopicSubscriber。我们可以用消息选择器来创建消息使用者,消息选择器允许客户机根据消息选择器指定的标准选择消息子集。欲了解详细信息,请参见第 8.7 节消息选择器(见本书第 289页)。消息使用者客户机可以同步接收消息,也可以让消息在到达时异步送达。客户机可以利用其接收方法之一从消息使用者请求下一条消息。接收有几种不同的形式,允许客户机登记或等待下一条消息。客户机可以向消息使用者注册 MessageListener 对象。当消息到达消息使用者时,它是通过调用 MessageListeners onMessage 方法来送达消息的。欲了解更多信息,请参见第 8.6节异步处理(见本书第 285 页)。245在 PTP 模型中,QueueReceiver 是利用 QueueSession 对象上的 createReceiver()方法创建的。该方法采用的是从何处接收消息定义的 Queue 参数。请参见如下的例子:QueueReceiver queueReceiver session.createReceiver(ioQueue);在发布预订模型中,TopicSubscriber 对象是利用 TopicSession 对象的 createSubscriber()方法创建的。请参见如下的例子:TopicSubscriber sub session.createSubscriber(topic);接收消息接收消息 消息是用消息使用者接收的。在 PTP 消息发送中,应当用 QueueReceiver 对象来接收消息,而在发布预订消息发送中,则应当用 TopicSubscriber 对象来接收消息。在 PTP 模型中,您可以利用 QueueReceiver 对象的接收方法来接收消息。请参见如下的例子:Message inMessage queueReceiver.receive(800);指定的参数是以毫秒为单位的超时。此方法发出调用,以接收指定超时间隔内到达的下一条消息。在发布预订模型中,我们利用 TopicSubscriber 的 receive()方法来接收预订。请参见如下的例子:Message inMsg sub.receive();这段代码执行了带有等待的获取方法。重点:重点:请注意,连接是线程安全的,但会话、消息生成器和消息使用者则不是。我们建议的做法是对每个应用程序线程使用一个会话。在 MQSeries 条款中,连接为临时队列提供了作用域。它也提供了地方,可以用来储存参数,该参数控制如何连接到 MQSeries。举例来说,这些参数就是队列管理器名和远程主机名(如果您使用 MQSeries Java 客户机连接的话)。会话包含 HCONN,因此定义了事务处理作用域。消息生成器和消息使用者包含 HOBJ,它定义了向其写入或从其读取的特定队列。请注意,正常的 MQSeries 规则是适用的。在任何给定时间上,每个 HCONN 只能进行一个单一的操作。因此,不能同时调用消息生成器或与会话相关的消息使用者。246这与 JMS 每个会话只有单一线程的限制是一致的。放置方法可以使用远程队列,但获取方法只能适用于本地队列管理器上的队列。一般 JMS 接口是进一步划分为更具体的版本子集,该子集为点到点以及发布预订行为。点到点版本如下:?QueueConnection QueueSession QueueSender QueueReceiver JMS 的关键理念就是,它编写的应用程序可以只在 javax.jms 中接口引用。我们强烈建议您这么做。所有各销售商特有的信息都包含在以下实施中:?QueueConnectionFactor TopicConnectionFactory-Queue-Topic 以上这些称作“管理对象”,即可以利用销售商提供的管理工具构造、且能被储存在 JNDI名称空间中的对象。JMS 应用程序可以从名称空间接收并使用这些对象,而不必知道由哪个销售商进行实施。MQSeries classes for Java Message Service 由许多 Java 类和接口构成,这些类和接口是以 Sun 的接口和类 javax.jms 包为基础的。应当用下面所列的 Sun 接口和类编写客户机,我们将在下面各节中详细描述这些接口和类。可实施 Sun 接口和类 MQSeries 对象的名称具有“MQ”作为前缀(如果对象描述中没有做出其它规定的话)。描述包括有关 MQSeries 对象与标准 JMS 定义存在任何偏差的细节。事务处理事务处理 会话是在客户机和消息发送系统之间的连接上一系列被发送和接收的消息。当创建会话时,它可以是非事务处理的(默认)也可以是事务处理的。事务处理会话保证一组消息要么都被发送接收,要么都不被发送接收。非事务处理会话意味着消息被分别发送和接收。在线购物就是事务处理会话的一个实例。客户打开订单(开始事务处理)。客户选择的每项商品都是一条在订单中添加商品的消息。客户关闭订单(结束事务处理)。如果发送器提交了事务处理,那么将发送组中所有的消息。如果发送器回退事务处理的话,那么将不订购任何商品项目。2478.3 JMS消息消息 JMS 提供不同的消息类型。每种类型都包括有关其内容的某些信息。JMS 中定义的消息类型如下:?BytesMessage?MapMessage?ObjectMessage?StreamMessage?TextMessage JMS 消息由以下三部分构成:?标题 标题字段包括供应方用于路由和确认消息的信息,以及客户机可以利用的信息。?属性 除标题中的字段外,JMS 消息还为添加可选的标题字段到消息提供功能。这些属性可以分为:-应用程序特定属性,客户机为处理消息用这些属性添加进程特定信息;-标准属性,即 JMS 特定属性;-供应方特定属性,原始客户机要求这些属性。?主体 这就是消息数据部分的所在。JMS 提供不同类型的消息主体,包括大部分当前正被使用的消息发送风格。8.3.1 映射映射JMS消息到消息到MQSeries消息上消息上 MQSeries 消息有三个组成部分:?MQSeries 消息描述器(MQMD);?MQSeries MQRFH2 标题;?消息主体。248MQRFH2 标题是可选的。MQRFH2 标题是具有固定部分和可变标题部分的可扩展的标题。固定部分以标准 MQSeries 标题模式为模型。MQRFH2 标题既可以携带与消息内容相关联的 JMS 特定数据,又可以携带不直接与 JMS 相关联的其他信息。我们用两种方法将 JMS 消息翻译或转化为 MQSeries 消息。?映射 映射是将 JMS 消息标题和消息属性翻译到有相应 MQMD 字段的相应 MQMD 值。?拷贝 如果 JMS 消息标题和消息属性值不具有相应的 MQMD 字段的话,JMS 标题字段或属性将被传递,并可能作为 MQRFH2 标题中的一个字段被转化。是否包括 MQRFH2 标题是可选的。在发送消息中,JMS 目的地类的标记决定是否包括它。该标记可以在定义 JMS 管理对象时用 JMSAdmin 工具来设定。管理员可以设置MQSeries 目的地的 TargetClient 值为 JMSC.MQJMS_CLIENT_NONJMS_MQ,从而显示出 JMS 客户机正与非 JMS 客户机通讯。由于 MQRFH2 标题携带着 JMS 特定信息,因此如果发送器知道接收客户机是 JMS 客户的话,您就应当包括它。如果接收器不是 JMS客户机,那么就应当省略 MQRFH2 标题。处理处理 JMS 消息类型消息类型 在本节中,我们将利用发货跟踪 ID(它作为 JMS 客户机的一条消息被发送)讲解可以如何使用不同的 JMS 消息类型。使用使用 TextMessage 类类 消息中的信息可以作为人类可以阅读的文本字符串发送,客户机也可以读取并处理或者显示该字符串。我们可以如下将跟踪 ID 作为 TextMessage 对象中的字符串发送:String trackingId;TextMessage message;message session.createTextMessage();message.SetText(trackingId);249使用使用BytesMessage类类 在 BytesMessage 中,信息是以二进制格式发送的。消息中的信息可以作为字节数组构件。可以如下准备这样的消息:byte trackingId;BytesMessage message;message session.createBytesMessage();message.writeBytes(trackingId);使用映射消息使用映射消息 在映射消息中,信息可以作为名值对发送。这样,消息本身可以包括消息所储存数据的元数据。在我们所用的例子中,发送消息请求 trackingId 上的信息,名(元数据)可以是 trackingId,实际值(比如说 AMX100000)将是名值对的值。消息可以如下构造:String attributeName“trackingId”;String attributeValue“AMX100000”MapMessage message;message session.createMapMessage();message.setString(attributeName,attributeValue);提示:如果值部分是较长的数据类型的话,那么您可以使用消息 setLong 方法。请根据您处理的数据类型选择合适的方法。使用流消息使用流消息 在流消息中,与映射消息相似,消息可以由顺序写入的各种字段构成,每个字段都有其自己原始的类型。在映射消息中,客户机可以设置映射中任意数量的字段,处理客户机则可以读取特定的字段而不必处理整个映射。但是,在流消息中,即便处理客户机仅对流消息中的字段子集感兴趣,客户机仍必须读取消息中的每个字段(再摒弃它不感兴趣的字段)。此二者的另一个重要差别就是,在映射消息中,字段顺序并不重要,但在流消息中,字段是以写入顺序读取的。流消息可以如下构造:String attributeName“trackingId”;String attributeValue“AMX100000”;250StreamMessage message;session.createStreamMessage();message.writeString(attributeName);message.writeString(attributeValue);使用对象消息使用对象消息 对象消息可被用来将 Java 对象作为一条消息传递,该消息就是接收客户机可以在对象中利用方法提取数据的消息。在下面的例子中,我们使用的是跟踪对象:public class TrackingObject private String attributeName;private String attributeValue;public void setAttributeName(String name)attributeName name;public void setAttributeValue(String value)attributeValue value;public String getAttributeName()return attributeName;public String getAttributeValue()return attributeValue;Using the above tracking object we can sent the tracking information as a tracking object.(利用以上跟踪对象,我们能发送作为跟踪对象的跟踪消息)We can construct such a message as:(我们能构造如下的消息)String attributeName“trackingId”;String attributeValue“AMX100000”;TrackingObject trakingObject new TrackingObject();ObjectMessage message;trackingObject.setAttributeName(attributeName);trackingObject.setAttributeValue(attributeValue);message session.createObjectMessage();message.setObject(trackingObject);251在接收方,客户机可以使用跟踪对象的获取方法来提取数据。消息识别消息识别 如果客户机指定 JMS 使用者的消息应被显式识别的话,那么 JMS 消息也支持使用识别方法。如果客户机使用自动识别的话,那么将忽略识别调用。消息识别有三种类型。消息识别的类型是在会话创建时指定的。这些不同的类型如下:?AUTO_ACKNOWLEDGE 在 AUTO_ACKNOWLEDGE 模式中,当消息成功从调用返回到接收器,或消息使用者注册的处理消息的消息侦听器成功返回时,消息会话将自动识别消息。Session session queueConnection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);?CLIENT_ACKNOWLEDGE 利用 CLIENT_ACKNOWLEDGE 模式,客户机通过调用消息上的识别方法显式并确认消息。Session session queueConnection.createQueueSession(false,Session.CLIENT_ACKNOWLEDGE);Then once the message is processed,the client can issue(然后一旦处理完消息,客户机就能发行)message.acknowledge();method to acknowledge the message.(方法以确认该消息)当使用 CLINET_ACKNOWLEDGE 模式时,我们在处理消息过程中必须注意避免大量未识别消息的积累,未识别消息的积累可能导致资源耗尽,带来失败。?DUPS_OK_ACKNOWLEDGE DUPS_OK_ACKNOWLEDGE 模式命令会话迟钝地确认消息送达。如果 JMS 失败的话,其结果就可能是重复消息发送。允许处理重复消息的使用者应当使用这种模式。在客户机允许重复消息的情况下,利用这种模式可以获取一些效能改善,因为会话在避免重复消息时的开销较小。2528.3.2 JMS补充特性补充特性 JMS 还包括其他一些特性:?异步消息送达-使用消息侦听器概念;-使用基于事件的模型,它在事先设定的事件上触发指定的函数。JMS 客户机可以注册侦听器对象,它可以实施具有消息使用者(消息接收器)的MessageListener 接口。当注册使用者的消息到达时,我们可以调用 listeners onMessage 方法让消息对消息使用者可用。?消息选择器-基于内容的特定消息接收-使用基于 SQL92 的查询函数 JMS 消息具有向 JMS 消息标题(在消息实际主体外)提供用户定义元数据的功能。JMS程序可以利用这一功能根据选择标准选择消息子集,换言之,JMS 客户机可以仅选择那些自己感兴趣的消息。8.4 MQSeries JMS实施实施 用 MQSeries 实施 JMS 的重点如下:?支持的平台:AIX,HPUX,Windows NT,Solaris 和 Linux?由包括关键功能的 JAR 文件构成-com.ibm.mq.jms.jar-com.ibm.mq.jar?定义管理对象到 JNDI 名称空间的管理工具:-JMSAdmin?作为产品延伸可以通过网络下载获取?MQSeries classes for Java 和 JMS with MQSeries V5.2 8.4.1 MQSeries JMS的安装的安装 为了使 JMS 支持 MQSeries,您必须安装并实施 JMS 接口的 Java 类。JMS classes for MQSeries 可以从下述 IBM 网站的 MA88 SupportPac 下载获取:253http:softwaretsmqseriestxppacs 此 SupportPac 是免费的。您可以根据支持的平台下载合适的版本,并按照随 SupportPac提供的安装说明进行安装。重点:重点:当您在安装 JMS SupportPac 时,位于 MQSeries 安装的 Java 次级目录中的所有文件都会在安装过程中备份,新文件拷贝自 SupportPac。如果在您的上下文中已经安装了AMI 支持,那么您可能需要重新安装 AMI SupportPac。一旦您已安装了 JMS SupportPac,为了用 JMS 运行发布预订应用程序,您还需要运行称作 MQJMS_PSQ.mqsc 的 MQSC 脚本,它位于 MQSeries 安装目录下的 javabin 次级目录中。为了在默认的队列管理器上运行脚本,请从操作系统命令行窗口中运行以下命令:runmqsc ToolsWebsphere Test Environment(见图 82)。257 图82 从VisualAge for Java步骤一启动持久名服务器?在左手边的窗格中选择持久名服务器并输入参数以连接到持久名服务器的配置数据库,请看图 83;258 图83 持久名服务器配置画面 重点:重点:在默认情况下,持久名服务器使用端口号 900。如果您已经指定了不同的端口的话,那么为 JNDI lookup 使用名服务器的程序就应当包括 PROVIDER_URL 参数中的端口号。?点击 Start Name Server 按钮启动持久名服务器。8.4.8 为配合使用为配合使用JMS配置配置VisualAge for Java 设置 VisualAge for Java 与 JMSAdmin 配合库或开发 JMS 应用程序的相关步骤如下:?校验 IBM 企业版库和 IBM WebSphere 监测上下文已加载入库空间;?调入以下 JAR 文件到项目中。可以在 MQInstallationDirectoryJava 下找到这些 JAR文件。我们在 VisualAge for Java 中已创建了名为 JMSTest 的新项目,该项目将用于以下的实例。-com.ibm.mq.jar-com.ibm.mqbind.jar-com.ibm.mqjms.jar-com.ibm.mq.iiop.jar 259-jms.jar-jndi.jar-ldap.jar-fscontext.jar-providerutil.jar?添加 MQSeriesInstallDirectoryjavalib 目录到 VisualAge for Java 库空间类路径。我们可以通过选择 Window OptionsResources Edit 和添加目录来实现这一目的(请参见图 84)。图84 设置VisualAge for Java库空间类路径 260?如果您希望在访问队列管理器时使用绑定模式的话,那么路径系统环境变量就应当包括 MQSeriesInstallDirectoryJavabin 目录。该目录包括 mqjbnd02.dll,在使用绑定模式时要求具有该文件。8.4.9 用用JMSAdmin配合配合VisualAge for Java管理管理JMS JNDI对象对象 在本节中,我们将讲解如何定义和管理用 MQSeries JMS 管理工具 JMSAdmin 配合VisualAge for Java 实施 JMS 时所需的 JNDI 对象。我们将在本章下面的编程样例中介绍如何使用工具处理对象,既包括点到点模式,又包括发布预订消息发送模式。被使用的被使用的 MQSeries 对象对象 表 81 列出了程序样例中用到的 MQSeries 对象。表81 程序样例中用到的MQSeries对象 对象名对象名 描述描述 SAMPLE.QMGR1 程序样例中将要使用的队列管理器 PTP.QUEUE.LOCAL 点到点样例中使用的队列 PTP.REPLY.QUEUE.LOCAL 请求回复发送回复消息所用的队列 JMS.SVR.CHNL 客户机连接所用的服务器连接通道 SYSTEM.JMS.ADMIN.QUEUE JMS 发布预订管理队列 SYSTEM.JMS.PS.STATUS.QUEUE JMS 发布预订状态队列 SYSTEM.JMS.REPORT.QUEUE JMS 发布预订报表队列 SYSTEM.JMS.MODEL.QUEUE JMS 发布预订预订器模型队列。(预订器使用该模型队列为预订创建永久队列)SYSTEM.JMS.ND.SUBSCRIBER.QUEUE JMS 发布预订默认非可持续共享队列(非可持续预订器使用的默认共享队列)SYSTEM.JMS.ND.CC.SUBSCRIBER.QUEUE JMS 发布预订 ConnectionConsumer 功能的默认非可持续共享队列 SYSTEM.JMS.D.SUBSCRIBER.QUEUE JMS 发布预订默认可持续共享队列(可持续预订器使用的默