用AMI编程 - IBM · 89 4 用ami编程...

44
89 4 AMI编程 本章将概括介绍应用程序消息接口,讲解什么是 AMI 以及如何应用 AMI。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:SC345604

Transcript of 用AMI编程 - IBM · 89 4 用ami编程...

Page 1: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

89

4 用AMI编程

本章将概括介绍应用程序消息接口,讲解什么是 AMI 以及如何应用 AMI。如欲了解更

多有关信息,请参见《应用程序消息接口参考》编号:SC34-5604。

Page 2: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

90

4.1 概览

应用程序消息接口(AMI)是对现有 MQSeries API 的最新补充。其可向程序员提供一

种可以用于处理队列管理器对象非常简单的接口。利用 AMI,程序员不必深入了解所有

MQI调用,他们只要专注于应用程序的商业逻辑即可。这就意味着在编程时出现的错误

更少,具有更高的处理业务及技术改变的灵活性。AMI减少了编写新应用程序所需的代

码数量。

每种编程模式都有不同的调用。举例说来,如果程序员希望编写发布/预订应用程序代码,

那么他将必须采用不同于编写请求/回复应用程序的程序员所采用的调用。单个函数之中

的结构更少,但是动词会更多。许多函数现在都是中间件层的一部分,在中间件层,企

业确立的一系列策略代表应用程序得以应用。AMI与包括 Java、C和 C++等在内的标准

编程语言已绑定。

AMI允许中央集中式控制和灵活的改变管理,为点到点模型提供高级接口,可以进行发

布/预订工作。AMI的重要特点是,其是独立于运输和消息发送基础设施的。

可采用以下方式发送和接收消息 AMI:

发送-遗忘,不需要回复。

分配表,将消息发送到多个目的地。

请求/回复,发送消息的应用程序需要请求消息的回复。

发布/预订,由代理管理消息的分配。

第 91页上图 4-1所示的就是一个简单的发送-遗忘应用程序实例。

Page 3: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

91

图 4-1 AMI发送-遗忘应用程序实例

利用 AMI,程序员通常需要处理三个概念:

消息,或者说交换的是“什么”。消息包括:

- 标题信息,确定消息及其属性。

- 消息主体,包含应用程序数据。应用程序数据可以由应用程序生成,也可以由

消息服务 API生成。

在采用 MQI 的 MQSeries 应用程序中,消息属性是用 MQI 显示设定的,因此

应用程序设计人员必须理解其目的是什么。利用 AMI 工作时,消息属性包括

在消息对象中,或由系统管理员设定的策略所定义,因此程序员就不必再关心

这些细节。

策略,或者说将要“如何”处理消息。其包含优先级或交付确认等信息。任何数

量的应用程序都可以利用相同的策略,而且任何应用程序都可以利用超过一个的

策略。IBM 提供了一套通用或默认策略,此外,其也提供了开放式策略处理器框

架,该框架允许第三方软件销售商创建更多策略。如果必须修改策略的话,那么

通常来说,我们不必修改应用该策略的应用程序。

Page 4: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

92

服务,或者说消息将被发送到“何处”或应从“何处”接收消息。就MQSeries而

言,这是指队列、分配表等。服务可以是指由单个应用程序提供服务的单个目的

地,也可以是指目的地列表或消息代理。服务通常定义在储存库(REPOSITORY)

中,其可指定到消息发送网络中真实资源的映射。储存库可以定义不同类型的服

务。服务由 AMI暗示打开和关闭。

储存库可为服务及策略提供定义。如果服务名或策略名在储存库中找不到,或者 AMI

应用程序没有储存库,那么就可采用集成在 AMI中的定义。将储存库定义保存在 XML

格式的储存库文件中。这些定义可以通过管理工具进行更改,但只能在Windows平台上

才可获得该管理工具。

利用标准文件共享工具或者简单的文件发送,我们可以在不同的平台上共享储存库文

件。重要的是要明确 AMI 应用程序不管具备或不具备储存库时都可以运行。如果没有

储存库,那么就将使用默认值。

在管理工具中,被称为“服务点”(service point)的单个定义可代表储存库中发送者和

接收者的定义。利用管理工具,我们可以界定义如下对象:

服务点

分配表

发布者

预订者

策略

不管有无相对应的储存库定义,我们都可以创建策略以及除分配表之外的服务。只有在

创建服务点之后才可创建分配表。利用储存库创建服务或策略时,必须包含专用类型的

定义,其命名应与应用程序所指定的名称相对应。

举例来说,创建名为“ORDERS”的发送者对象时,储存库必须有一个名为“ORDERS”

的服务点定义。利用储存库创建的策略和服务,其内容由称为命名储存库定义进行初始

化。无储存库的策略和服务,其内容由在默认系统定义中定义的值进行初始化。管理工

具只是MQSeries AMI SupportPac (MA0F)for Windows NT的一部分,并只能安装在

运行Windows NT 4.0或Windows 2000的机器上。启动管理工具时,应选择 IBM MQSeries

AMI->IBM MQSeries AMI Administration Tool,或者从Windows资源管理器中双击文

Page 5: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

93

件\amt\AMITool\amitool.bat。图 4-2显示了 AMI管理工具。

图 4-2 AMI管理工具

AMI具有两个不同的角色:管理角色和开发角色。

在开发作用中,开发者专注于利用管理员提供的资源发送信息。这一作用不需要深入了

解MQSeries。

管理作用则负责创建和定义储存库中的服务和策略。换言之,管理员定义信息将被发送

到“哪里”以及“如何”发送信息。这一作用要求深入了解MQSeries。

Page 6: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

94

利用 AMI,简化连接代码以便在发送或接收消息时确定服务或策略。利用管理工具在储

存库中定义策略和服务,因此管理员可以修改它们而不会对应用程序造成任何影响。利

用 AMI,我们可以在下面一种或更多种情况中交换消息:

与另一个使用 AMI的应用程序交换。

与使用任何不同MQSeries API (MQI、MQSeries Classes for Java、ActiveX等)

的应用程序交换。

与消息代理交换(MQSeries发布/预订或WebSphere MQ Integrator)。

AMI简化了发布/预订应用程序的创建。发布/预订环境中的许多配置都存在储存库中,

应用程序从中获取参照。如果程序员希望寻找简单的、毋需深入了解MQSeries的 API,

那么我们就会推荐 AMI。AMI 可以通过 SupportPac (MA0F)获得,也可以从下面的

IBM网站地址中下载:

http://www.ibm.com/software/ts/mqseries/txppacs/

提示:在尝试采用 AMI 的发布/预订功能前,必须先安装 MQSeries Publish/Subscribe

SupportPac (MA0C)。

4.2 平台和语言

正如我们在第 4.1节《概述》(见本书第 90页)中所介绍的那样,AMI适用于 C、 C++

和 Java语言。其可应用于以下平台上:

Windows NT和Windows 2000

AIX 版本 4.3或更高版本

Sun Solaris 2.6 或 2.7

HP-UX版本 11.0

AS/400版本 4R4或更高版本

AMI也适用于 COBOL,但仅限于 OS/390版本 2R6或更高,以及 CICS版本 4.1和 IMS

版本 5.1。

AMI的过程应用程序编程有两个级别:

高级:程序 C和 COBOL(在 OS/390接口上)。由于操作是隐式的,因此 AMI函

数数量减少。

Page 7: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

95

对象级:Java和 C++类接口/对象风格 C接口。

提示:C高级接口包括适应大多数应用程序要求的功能。但是,如果我们需要更多的功

能的话,那么可以采用 C对象接口和高级接口的组合。

AMI除了可提供简单的接口来处理队列管理器对象外,其对每种编程语言都有一个自然

的风格。例 4-1显示了采用 C API的发送-遗忘应用程序。

实例 4-1 C语言编写的简单发送-遗忘应用程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <amtc.h> #include <time.h> int main(void) { /* 创建会话*/ hSession = amSesCreate( SAMPLE_SESSION_NAME, &compCode, &reason); hPol = amSesCreatePolicy( hSession, SAMPLE_POLICY_NAME, &compCode, &reason); hSender = amSesCreateSender( hSession, SAMPLE_SENDER_NAME, &compCode, &reason); success = amSesOpen( hSession, hPol, &compCode, &reason); success = amSndOpen( hSender, hPol, &compCode, &reason); success = amSndSend( hSender, hPol, AMH_NULL_HANDLE, AMH_NULL_HANDLE, strlen(sampleMsg), (unsigned char *)sampleMsg, AMH_NULL_HANDLE, &compCode, &reason ); success = amSesDelete( &hSession, &compCode, &reason ); endSample(EXIT_SUCCESS); }

例 4-2中出现的应用程序与例 4-1中的发送-遗忘应用程序相同,不过这回它是用 Java

API编写的。请注意,这两种编程语言的每一种都具有自然的风格。

例 4-2 用 Java编写的简单发送-遗忘应用程序 import java.util.*; import com.ibm.mq.amt.*; . . . public void main() { mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(SAMPLE_SESSION_NAME); myPolicy = mySession.createPolicy(SAMPLE_POLICY_NAME);

Page 8: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

96

mySender = mySession.createSender(SAMPLE_SENDER_NAME); mySendMSG = mySession.createMessage(SAMPLE_MESSAGE_NAME); mySession.open(myPolicy); mySender.open(myPolicy); String sampleMessage = new String("Sample message"); mySendMSG.writeBytes(sampleMessage.getBytes()); mySender.send(mySendMSG); mySender.close(myPolicy); mySession.close(myPolicy); }

4.3 库和包

现在,我们已经了解了可以用来编写 AMI 应用程序的不同编程语言,接下来,我们就

必须了解用于编写 AMI应用程序的不同的库。如果利用 C语言来编写应用程序的话,

那么 AMI会提供头文件,称为 amtc.h。该文件包括 AMI所用的所有函数、结构和常量。

该头文件必须包含在应用程序中,我们可以用下面的语句来做到这一点:

#include <amtc.h>

图 4-1显示了在支持 AMI的不同平台上 amtc.h文件所处的位置。

表 4-1 AMI C 头文件的位置

操作系统平台 位置

AS400 QMQAMI/H

UNIX(包括 AIX, HP-UX和 Solaris) {MQSeries目录}/amt/inc

Windows {MQSeries目录}\amt\include

OS/390 hlq.SCSQC370

提示:在编译时间内,程序必须能够访问 amtc.h文件。

就 C++而言,AMI还可提供另一个头文件,称为 amtcpp.hpp。该头文件包括 C++的函数、

结构和常量,与 C语言的头文件完全一样。同样,amtcpp.hpp也必须包含在应用程序中。

我们同样也可以用下面的语句来实现这一目的:

#include<amtcpp.hpp>

Page 9: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

97

表 4-2显示了 amtcpp.hpp文件在支持 AMI的不同平台上的位置。

表 4-2 AMI C++头文件的位置 操作系统平台 位置 AS/400 QMQAMI/H UNIX(包括 AIX、HP-UX和 Solaris) {MQSeries 基目录}/amt/inc Windows {MQSeries 基目录}\amt\include

提示:在编译时间内,即便 amtcpp.hpp是唯一在使用中的头文件,程序也必须可以访问

amtc.h和 amtcpp.hpp这两个文件。

如果开发人员希望使用 Java API的话,那么 AMI可提供包括构成 AMI package for Java

所有类的 JAR文件。

Java包:com.ibm.mq.amt

Java JAR文件:com.ibm.mq.amt.jar

为了使用 AMI package for Java,我们必须利用导入语句将其导入 Java应用程序:

import com.ibm.mq.amt.*;

提示:JAR 文件必须是 CLASSPATH 环境变量的一部分(这必须在编译和运行 Java 应

用程序的环境中完成)。

表 4-3显示了 AMI JAR文件在支持 AMI不同平台上所处的位置。

表 4-3 AMI Java JAR文件的位置 操作系统平台 位置 AS/400 /QIBM/ProdData/mqm/amt/Java/lib UNIX(包括 AIX、HP-UX和 Solaris) {MQSeries 基目录}/java/lib Windows {MQSeries 基目录}\java\lib

如果要使用 COBOL的话,那么 AMI提供以下副本(copybooks)来帮助程序员进行应

用程序编程:

AMTV:该副本包括常量和返回代码。

AMTELEML:该副本包括 AMELEM数据结构的定义,用于在 AMI中传输变量名

Page 10: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

98

和值等因素信息。该副本提供不带任何起初始值的定义。

AMTELEMV:该副本与 AMTELEML 副本内容相同,但二者唯一的差别在于,

AMTELEMV副本可提供带有起始值的定义。

这些副本安装在用于 OS/390 库 hlq.SCSQCOBC 的 MQSeries 中。我们建议您利用

AMTELEMV 定义 AMELEM 结构。这将提供默认起始值,其可保证 strucId 和 version

字段具有有效值。如果这些字段的值无效,那么 AMI将不接受这些值。

表 4-4显示了由 AMI支持的 C、COBOL、C++,以及 Java语言编译程序:

表 4-4 语言编译器 操作系统 平台

所支持的编译器

AIX 用于 C++ 5.0版本的 VisualAge JDK 1.1.7和更高

OS/400

用于 Java(5769JV1)的 AS/400 Developer Kit 用于 AS/400(5769CX2)的 ILE C 用于 AS/400(5799GDW)的 ILE C++ 用于 C++ for 0S/400(5716CX4)的 Visual Age

HP-UX

HP aC++ B3910B A.03.10 HP aC++ B3910B A.03.04(970930)支持库 JDK 1.1.7和更高

OS/390

OS/390 C/C++ 版本 2(第 6次发行)或更高 用于 OS/390 & VM 版本 2(第 1次发行)或更高的 IBM COBOL 用于MVS 和 VM 版本 1(第 2次发行)或更高的 IBM COBOL

Sun Solaris

Workshop Compiler 4.2(带 Solaris 2.6) Workshop Compiler 5.0(带 Solaris 7) JDK 1.1.7或更高

Windows

Microsoft Visual C++ Version 6 JDK 1.1.7或更高

如欲了解如何在所有支持的语言中准备并运行 AMI 应用程序的更多信息,请参见

MQSeries应用程序消息发送接口文档。

4.4 体系结构模型

AMI可提供以下对象:

Page 11: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

99

会话:用以创建新的 AMI会话,并用以控制事务处理支持。这是在创建和管理所

有其他对象(消息、策略、接收者等)前第一个需要初始化的对象。

消息:该对象包含消息数据以及发送或接受消息时用到的消息描述符结构。

发送者:代表消息发送目的地的一项服务。MQOD结构包含在该对象中。

接收者:代表消息接收来源的一项服务。MQOD结构也包含在该类中。

分配表:包含发送者服务列表,提供目的地列表。

发布者:包含发送者服务,其中目的地是一个发布/预订代理。

预订者:包含发送者服务,将预订和取消预订消息发送至发布/预订代理,也包括

一个接收者服务,接收来自代理的发布内容。

策略:定义应当如何处理消息,包括优先级、持久性,以及其是否应包括在工作

单元中等项目。

发送者、接收者、分配表、发布者和预订者都是服务。直接连接到消息传输层的唯一对

象是发送者和接收者。因此,分配表和发布者对象包含发送者,而预订者对象包含发送

者和接收者。图 4-3显示了 AMI体系结构模型,并反映了每个对象如何与其他各个对

象进行互动。

Page 12: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

100

图 4-3 AMI体系结构模型

消息、服务和策略对象是由会话对象创建和管理的。会话对象也提供工作单元的范围。

连接、发送者和接收者对象的组合可提供消息的传输。

程序员可以利用系统默认提供的消息属性、服务和策略对象,也可以利用管理员定义的、

储存在储存库中的属性。除了以上提到的对象之外,AMI 还为 C++和 Java 提供了更多

的对象定义。

这些对像包括:

会话库:该对象用以创建会话对象。没有会话库,就不能创建会话对象。

协助对象和异常对象(Helper and Exception objects)。

Page 13: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

101

4.5 采用AMI编程

在以下各节中,我们将介绍在处理队列管理器对象时,如何将 AMI 应用到常见步骤中

去,这在第一章《入门和模式》(见本书第 3页)已讨论过。本节所用的实例是采用 Java

接口编写的。如欲了解如何采用其他支持 AMI 的编程语言发出调用,请参考应用程序

消息发送接口文档。

4.5.1 连接到队列管理器 正如在其他 MQSeries API 中一样,在尝试访问任何队列服务器对象之前,我们都必须

连接到队列服务器。我们可以利用两个 AMI Java调用实现这一目的。首先,需要创建

新的会话库对象。在此应记住,为了创建会话对象,必须至少有一个会话库对象(这只

适用于 C++和 Java)。用来创建会话库的命令是:

SessionFactoryObject = new AmSessionFactory(String factoryName)

FactoryName 是一个可选参数。该字符串实际上就是储存库和主文件所在的目录,其也

可以是完全指定的目录,包括文件所在的路径,例如:C:\Program Files\MQSeries\amt。

如果该参数没有指定,那么我们将使用 AMT_DATA_PATH环境变量所指定的值。该环

境变量通常是在MQSeries AMI SupportPac(MA0F)安装时设定的。

创建会话库对象之后,我们可以定义新的会话对象。通过利用 AmSessionFactory 类的

createSession()方法来进行这一工作。

mySessionFactory.createSession(String sessionName)

sessionName 参数是我们可以用来确定会话对象的名。一旦会话库初始化且创建了会话

对象,应用程序就可以处理 MQSeries 对象了。在第三章《采用 MQI 编程》(见本书第

23页)中,我们了解到,为了使用MQI API连接到队列管理器,必须在MQCONN调

用中指定队列管理器。在 AMI中,队列管理器名是从位于{MQSeries基目录}/amt的主

文件(默认情况下是 amthost.xml)中读取的。例 4-3显示了用来连接到称为 ITSOH队

列管理器的主文件样例。如果 defaultConnection标签没有指定队列管理器的话,那么将

采用默认的队列管理器。

Page 14: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

102

例 4-3 主文件样例 <?xml version=”1.0” encoding=”UTF-8” ?> <queueManagersNames defaultConnection=”ITSOH” connectionName1=”queueManagerName1” connectionName2=”queueManagerName2” />

例 4-4显示了如何创建 AmSessionFactory对象,以及名为 ITSO的 AmSession对象。

例 4-4 创建新对象 private AmSessionFactory mySessionFactory = null; private AmSession mySession = null; // ------------------------------------------ // Since we are not specifying a name for the AmSessionFactory,(由于我们没有为 AmSessionFactory指定名称) // we expect the AMI files to be stored in the default(因而我们希望将 AMI文件存储在默认 // location. 位置) // ------------------------------------------ mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO”);

一旦创建了会话,我们在创建其他 AMI 对象时所采用的顺序就并不重要了。但是,我

们建议您以如下顺序对对象进行初始化:

1. 会话

2. 策略

3. 发送者/接收者/发布者/预订者/分配表

4. 消息

4.5.2 打开MQSeries对象 创建会话库和会话对象之后,下一步应创建/初始化其他 AMI对象。

创建策略

首先,我们需要创建策略对象。我们可以利用 AmSession类的 createPolicy()方法来达

到这一目的。

sessionObject.createPolicy(String policyName)

Page 15: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

103

如果我们所指定的 policyName 与储存库中已经存在的策略名相匹配,那么将会采用储

存库定义来创建策略。如果储存库中不存在这种策略名,则将采用默认值创建策略。在

例 4-5 中,我们可以看到如何创建 AMT.SAMPLE.POLICY。由于储存库已经定义了

AMT.SAMPLE.POLICY,因此该策略将用储存库已定义的值进行创建。

例 4-5 创建策略对象 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); }

创建策略之后,下一步就是根据应用程序要采用的设计模式来创建对象模式。对象类型

可以是:

发送者和/或接收者(也称服务点)

发布者

预订者

分配表

创建发送者

为了创建发送者对象,我们要用到会话对象的 createSender()方法。

sessionObject.createSender(String senderName);

如果指定的 senderName 与储存器中已存在的相匹配,那么将采用储存器中的定义来创

建发送者对象。如果不存在的话,那么将采用默认值来创建发送者。例 4-6 显示了如

何创建一个称为 AMT.SENDER.NAME的发送者。

例 4-6 创建发送者 AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null;

Page 16: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

104

mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySender = mySession.createSender(“AMT.SENDER.NAME”);

创建接收者

为了创建接收者对象,我们要用到会话对象的 createReceiver()方法。

sessionObject.createReceiver(String receiverName);

如果我们指定的 receiverName与储存器中已经存在的相匹配,那么将采用储存器中的定

义来创建接收者对象。如果不存在的话,将采用默认值来创建接收者。例 4-7 显示了

如何创建一个称为 AMT.RECEIVER.NAME的接收者。

例 4-7 创建接收者 AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmReceiver myReceiver = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); myReceiver = mySession.createReceiver(“AMT.RECEIVER.NAME”);

创建发布者

为了创建发布者对象,我们要用到会话对象的 createPublisher()方法。

sessionObject.createPublisher(String publisherName);

如果我们指定的 publisherName 与储存器中已经存在的相匹配,那么将采用储存器中的

定义来创建发布者对象。如果不存在的话,那么将采用默认值来创建发送者。发布者和

预订者所用的发送者和接收者点的服务类型必须在储存库中定义为MQRFH。这就会产

生 MQRFH 标题,包含发送/预订名/值等因素,这些将在消息发送时被加到消息中。如

欲了解更多信息,请参见应用程序消息发送接口文档。例 4-8 显示了如何创建称为

AMT.PUBLISHER.NAME的发布者。

Page 17: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

105

例 4-8 创建发布者 AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmPublisher myPublisher = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); myPublisher = mySession.createPublisher(“AMT.PUBLISHER.NAME”);

创建预订者

为了创建预订者,我们要用到会话对象的 createSubscriber()方法。

sessionObject.createSubscriber(String subscriberName);

如果我们指定的 subscriberName与储存器中已经存在的名称相匹配,那么将采用储存器

中的定义来创建预订者对象。如果不存在,将采用默认值进行创建。例 4-7 显示了如

何创建一个称为 AMT.SAMPLE.SUBSCRIBER的预订者。

例 4-9 创建预订者 public static void main() { . . . AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySubscriber = mySession.createSubscriber(“AMT.SAMPLE.SUBSCRIBER”); }

Page 18: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

106

创建分配表

为了创建分配表对象,我们要用到会话对象的 createDistributionList()方法。

sessionObject.createDistributionList(String distributionlistName);

如果我们指定的分配表名与储存器中已经存在的相同,那么将采用储存器中的定义创建

对象。如果不存在,将采用默认值创建分配表。在我们能使用分配表之前,管理员必须

首先定义发送者服务,再将这些服务定义为分配表的一部分。例 4-10显示了应当如何

创建分配表。

例 4-10 创建分配表 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySender = mySession.createDistributionList(“AMT.DISTRIBUTION.LIST”); }

图 4-4显示了储存库中称为 AMT.DISTRIBUTION.LIST的分配表是如何定义的。请注

意,也可在服务点段中定义作为分配表一部分的对象。

Page 19: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

107

图 4-4 称为 AMT.DISTRIBUTION.LIST分配表的定义

创建消息

为了创建消息对象,我们要用到以下 AmSession类的 createMessage()方法。

AmSession.createMessage(String messageName)

对应用程序而言,MessageName是具有意义的名称。例 4-11显示了一段代码样例,告

诉我们如何创建称为 ITSO.SAMPLE.MESSAGE.NAME的消息。

例 4-11 创建消息对象 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null;

Page 20: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

108

AmPolicy myPolicy = null; AmPolicy myPolicy = null; AmMessage mySendMSG = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySender = mySession.createSender(“AMT.SENDER_NAME”); mySendMSG = mySession.createMessage(“ITSO.SAMPLE.MESSAGE.NAME”); }

现在我们已经创建了对象,那么下一步就要打开这些已被定义的对象。利用 open()方

法来进行这一工作。举例来说,如果需要打开发送者对象,那么就要用到该发送者对象

的 open()方法。所有的打开调用都分享一个共同的参数,这就是策略对象参照。正如

我们在“创建策略”(见本书第 102页)这一部分中所看到的那样,该参照是用 AmSession

类的 createPolicy()方法创建的。如果没有指定策略,那么将采用系统默认策略。打开

方法的句法如下:

AmSession.open(AmPolicy policyObject);

AmSender.open(AmPolicy policyObject);

AmReceiver.open (AmPolicy policyObject);

AmPublisher.open(AmPolicy policyObject);

AmSubscriber.open(AmPolicy policyObject);

例 4-12显示了如何打开会话、发布者和接收者对象。

例 4-12 打开不同类型的对象 Open the session factory(打开会话库) Create the required objects (session, publisher, message, etc.)(创建所需对象(会话、发布者,消息等)) /.... myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySession.open(myPolicy); myPublisher.open(myPolicy); myRespReceiver.open(myPolicy);

Page 21: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

109

4.5.3 基本操作 在第 4.5.2节《打开 MQSeries对象》(见本书第 102页)中,我们讨论了如何创建并打

开不同的可用对象。现在既然我们已经创建并初始化了对象,接下讨论可对这些

MQSeries 对象进行哪些基本操作。这些基本操作包括获取消息、发送消息、发布和预

订消息。

可以在MQI中发送或接收消息之前,我们必须先打开队列,以获得输入或输出。在MQI

中,这被称为打开选项(MQOO_INPUT_SHARED, MQOO_OUTPUT)。在 AMI中,由

管理员给出这些定义,并将其保存在储存库中,因此在队列管理器对象打开或作为一部

分调用的时候,程序员不必对其做明确的定义。

发送消息

为了发送消息,我们要用到发送者类的 send()方法。请记住,在尝试发送消息之前,

必须创建至少四个对象(会话、策略、消息和发送者)。如果我们需要获得回复的话,

那么还必须创建接收者对象和另外的消息对象。

消息内容总是以字节形式发送的(Java 的本身形式),因此我们建议您在发送消息前用

getBytes()方法(Java 的本身方法)将消息转化成字节数组。一旦转化消息,接下来

就应当利用发送者类的 writeBytes()方法将其写入消息对象中。

senderObject.send(AmMessage messageObject, AmReceiver receiverObject/AmMessage

receivedMessage, AmPolicy policyObject)

另外,我们可以指定策略对象和/或接收者或另一消息对象。请记住,策略是指“如何”

处理消息。换言之,我们利用策略可以指定优先级,或者说如果送达消息时出现错误的

话,那么应当采取哪些行动,等等。

如果我们要求某种类型的回复,比如送达报告确认或远程应用程序的确认,那么我们就

必须根据希望如何处理回复而指定接收者对象或消息对象。例 4-13显示了发送消息样

例方法。

例 4-13 发送消息样例 public static void main() {

Page 22: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

110

AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmSender mySender = null; AmMessage mySendMSG = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySender = mySession.createSender(“AMT.SENDER_NAME”); mySendMSG = mySession.createMessage(“ITSO.SAMPLE.MESSAGE.NAME”); String sampleMessage = new String("Sample message"); mySendMSG.writeBytes(sampleMessage.getBytes()); mySender.send(mySendMSG); }

我们也可以同时将消息发送到多个目的地。我们可以利用 distributionList对象的 send()

方法做到这一点。如欲了解如何创建并打开分配表的更多信息,请参见第 4.5.2 节《打

开 MQSeries对象》(见本书第 102页)。例 4-14显示了将消息样例发送到多个目的地

的实例的方法。

例 4-14 将一条消息发送到多个目的地 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmDistributionList myDistributionLst = null; AmMessage mySendMSG = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); myDistributionLst = mySession.createDistributionList(“ITSO.DISTRIBUTION.LIST”); mySendMSG = mySession.createMessage(“ITSO.SAMPLE.MESSAGE.NAME”); String sampleMessage = new String("Sample message"); mySendMSG.writeBytes(sampleMessage.getBytes()); myDistributionList.send(mySendMSG); }

获取消息

为了获取消息,我们要用到接收者类的 receive()方法。

amReceiver.receive(AmMessage messageObject, AmSender senderObject, AmMessage

selectionmessageObject, AmPolicy policyObject);

Page 23: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

111

要该调用中有 4 个参数,但其中只有 messageObject 是始终需要的。接收的消息将被储

存在此参数中。如果发送应用程序请求回复的话,那么就必须指定 senderObject。

PolicyObject 用来指定等待时间间隔,或是否要求数据转换等。如果我们需要根据关联

性 ID(correlation ID)获得某个特定消息的话,那么就必须指定 selectionmessageObject。

我们在前面曾指出,当发送消息时,必须将其转化为字节数组,因此当接收消息时,我

们应当读取字节数组。

为了读取字节数组,要用到消息类的 readBytes()方法。例 4-15显示了如何接收消息。

例 4-15 接收消息 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmReceiver myReceiver = null; AmMessage myReceiveMSG = null; AmMessage mySendMSG = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“ITSO.SAMPLE.POLICY”); myReceiveMSG = mySession.createMessage(“ITSO.SAMPLE.MESSAGE.NAME”); myReceiver.receive(MyReceiveMSG); String sampleMessage = new String(MyReceiveMSG.readbytes(myReceiveMSG.getDataLength())); }

发布消息

发布消息时,应当遵从以下几个步骤。一旦打开消息和发布者对象,就需要为消息创建

新主题。该主题就是描述将要发布数据的词。我们用消息类的 addTopic()方法创建主

题。

messageObject.addTopic(String topicName)

唯一所需的参数就是 topicName,正如我们前面谈到的那样,其为描述将要发布数据的

词。

Page 24: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

112

添加主题之后,我们就可以发布消息了。为了发布消息,要用到发布者类的 publish()

方法。

publisherObject.publish(AmMessage messageObject, AmReceiver

receiverObject, AmPolicy policyObject)

messageObject是包含将发布消息的对象。只有在策略不指定发布者的隐式注册(implicit

registration)的情况下,才可以省略 receiverObject。总是应当指定MessageObject。如果

没有指定 policyObject,将采用默认定义。

例 4-16 显示了如何发布消息的样例代码。在该例中,没有指定 policyObject;因此我

们将采用默认定义。默认定义不要求发布者的隐式注册,因此不要求 receiverObject。

例 4-16 发布一条消息 Create and open required objects (session, policy, message and publisher) (创建并打开所需对象(会话、策略、消息以及发布者)) string pubMessage=”SUNNY”; mySendMSG.addTopic(“Weather”); mySendMSG.writeBytes(pubMessage.getBytes()); myPublisher.publish(mySendMSG);

预订消息

为了预订消息,应用程序应当就感兴趣的信息发送请求。我们通过在请求中包含主题来

实现这一目的。一旦请求完成,预订者就可以接收来自许多不同发布者的信息,而且也

可以将接收到信息发送给其他的预订者。为了在请求中包括主题,我们可以使用消息类

的 addTopic()方法。

messageObject.addTopic(String topicName)

topicName 是确认数据的一个名,该数据对预订者应用程序有用。对应用程序希望预订

的每个主题,都必须使用该调用。一旦应用程序定义了所有主题,就用预订者类的

subscribe()方法发送预订请求。

Page 25: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

113

subscriberObject.subscribe(AmMessage messageObject, AmReceiver

receiverObject, AmPolicy policyObject)

messageObject是我们利用 addTopic()方法向其添加主题的对象。该参数是可选的。将

匹配预订请求的发布内容发送到 receiverObject。但是,该参数并不总是需要的。另一种

接收匹配请求的发布信息的方法就是发出预订类的 receive()方法。

可以确定,也可以不指确定 PolicyObject。如确定,那么策略就包含匿名注册、仅接收

新发布内容等选项。如果未确定的话,那么将采用默认策略。如果 receiverObject 在预

订请求中未确定的话,那么可以利用 receive()方法接收发布内容。

subscriberObject.receive(AmMessage messageObject, AmMessage

selectionmessageObject, AmPolicy policyObject

messageObject 将包含所有已发布的消息,并在消息接收前进行隐式重置。只有在我们

希望根据关联性 ID 选择某个特定消息时才采用 selectionMessageObject。如果未确定的

话,那么就接收第一个可用的信息。可以确定 PolicyObject,也可以不确定。

一旦我们接收了符合预订请求所确定标准的所有消息,或者说我们不需要更多的消息

了,那么应用程序就可以取消预订,换言之,应用程序此时可以发出请求,这样就不会

再发送更多的消息了。

应用程序可以发送一个请求,取消预订其最初请求的所有主题,也可仅取消预订某个特

定主题。通过发出预订类的 unsubscribe()方法,我们可实现这一目的。

subscribeObject.unsubscribe(AmMessage messageObject, AmReceiver

receiverObject, AmPolicy policyObject)

messageObject 包含取消预订请求所应用的主题。如需要获得取消预订请求的确认,那

么必须发出 receiverObject。正如前面的调用一样,可以确定策略,也可以不确定。例 4

-17显示了如何应用我们在本节所讨论的这些调用。

例 4-17 预订消息

Page 26: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

114

int iCounter = 0; String topic = ”Weather”; mySendMSG.addTopic(“Weather”); mySubscriber.subscribe(mySendMSG, myPolicy); // Only 5 messages are expected(仅需要五个消息) for (iCounter = 0; iCounter < 5; iCounter++) mySubscriber.receive(myReceiveMSG, myPolicy); String myRequest = new String(myReceiveMSG.readBytes(myReceiveMSG.getDataLength())); System.out.println(myRequest); } // The application has received all the messages that it wanted so it proceeds(该应用程序已接收到了其所期望的所有消息,因而其会继续发送) // to send an unsubscribe request.(一个未预订的请求) mySubscriber.unsubscribe(mySendMSG, myPolicy);

4.5.4 删除会话并关闭连接 我们对队列管理器应用程序的工作完成之后,接下来就可关闭对象了。我们利用每个被

用对象的 close()方法来实现这一目的。另一种方法就是仅关闭会话对象。一旦关闭

该对象,其他对象也将关闭。但是,我们强烈建议您隐式关闭所有已打开的对象。

subscriberObject.close(AmPolicy policy Object);

sessionObject.close(AmPolicy policy Object);

receiverObject.close(AmPolicy policy Object);

publisherObject.close(AmPolicy policy Object);

distributionlistObject.close(AmPolicy policy Object);

所有这些 close()方法需要的唯一一个参数就是 policyObject。请记住,policyObject

也包含关闭选项,如关闭时删除动态队列等。如欲了解更多信息,请参见 MQSeries 应

用程序消息发送接口文档。

提示:最后一个必须关闭的对象是 sessionObject。一旦关闭 sessionObject,其他参照都

会无效。

Page 27: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

115

4.6 AMI和MQI的比较

我们已经讨论了 MQSeries 所提供的不同 API,现在,我们可以谈谈它们彼此之间的比

较。在这一节中,我们将对 AMI和MQI进行比较。

利用 MQI,消息目的地和消息的发送/接收选项均由应用程序管理,而利用 AMI,则由

策略管理。MQI 提供全部 MQSeries 函数支持,只考虑消息传输。AMI 提供较少的

MQSeries函数,但提供更多的功能性。

MQI 的编程接口属低级的(动词较少,但有很多结构),对不同语言(C、C++、Java

和 COBOL)来说,其 API都是相似的。AMI具有高级编程接口,这意味着其动词更多,

而结构更少,而且其 API 对每种不同的编程语言都有各自自然的风格。MQI 根据传输

而不同,AMI则独立于传输。

MQI 是 IBM 的所有,而 AMI 的子集符合开放应用程序组/开放应用程序中间件 API 标

准(C++和 Java)。

4.7 事务处理管理

为了使 AMI 发送和接收的消息成为事务处理工作单元的一部分,管理员必须利用 AMI

管理工具指定策略的同步点属性。在默认情况下,将同步点属性设为关闭。我们可以在

策略定义的 General标签中找到该属性。

控制事务处理的 API调用取决于正被使用的事务处理类型。此处有两种不同的情况:

当唯一的资源是MQSeries消息时:

在这种情况中,根据策略中就发送或接收对象所确定的那样,事务处理由同步点控

制下第一个发送或接收的消息来启动。多个消息可以包括在同一工作单元中。可以

用会话对象的 commit()方法提交事务处理,或者也可以用会话对象的 rollback()

方法取消事务处理。

例 4-18显示了MQSeries消息作为唯一资源的同步点控制实例。

Page 28: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

116

例 4-18 同步点控制 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmReceiver myReceiver = null; AmMessage myReceiveMSG = null; AmMessage mySendMSG = null; mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“ITSO.SAMPLE.POLICY”); myReceiveMSG = mySession.createMessage(“ITSO.SAMPLE.MESSAGE.NAME”); myReceiver.receive(MyReceiveMSG); // If no failures were found commit the action(如果未发现故障,请执行此操作) mySession.commit(myPolicy); String sampleMessage = new String(MyReceiveMSG.readbytes(myReceiveMSG.getDataLength())); // If some problems were found, don’t retrieve the message(如果发现一些问题,则不用检索消息) mySession.rollback(myPolicy); }

MQSeries作为 XA事务处理协调器(XA transaction coordinator)

在可恢复资源(如关系数据库)发生改变之前,须用 AmSession 类的 begin()方

法显式启动事务处理。而后,可以用 AmSession 类的 commit()方法提交工作单

元,或者用 AmSession类的 rollback()方法予以取消。例 4-19显示了MQSeries

作为 XA事务处理协调器的实例。

例 4-19 MQSeries作为 XA事务处理协调器 public static void main() { AmSessionFactory mySessionFactory = null; AmSession mySession = null; AmPolicy myPolicy = null; AmSender mySender = null; AmMessage mySendMSG = null; // Connect to the database(连接至数据库) mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“ITSO.SESSION.NAME”); myPolicy = mySession.createPolicy(“AMT.SAMPLE.POLICY”); mySender = mySession.createSender(“AMT.SENDER_NAME”);

Page 29: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

117

mySendMSG = mySession.createMessage(“ITSO.SAMPLE.MESSAGE.NAME”); mySession.Begin(myPolicy); // Update a table.(更新表) // If the update was successful then commit the action and send a message to(如果更新成功,则执行该命令,并发送一个消息) // another application(到另一应用程序) String sampleMessage = new String("Sample message"); mySendMSG.writeBytes(sampleMessage.getBytes()); mySender.send(mySendMSG); mySession.commit(myPolicy); // If problems occurred during the update, backout the changes(如果在更新过程中发现问题,则撤消更改) mySession.rollback(myPolicy); }

提示:如果使用外部事务处理协调器(如 Tuxedo),就可能出现另一种情况。在这种情

况下,我们利用外部事务处理协调器的 API 调用来控制事务处理。尽管没有使用 AMI

调用,但同步点属性仍必须在调用使用的策略中确定。

4.8 分组

AMI 允许将一系列相关消息包含在消息组中或作为消息组发送。组上下文信息(group

context information)随每个消息发送,以使消息系列得以保存,并可由接收程序获得。

为了将消息包含在消息组中,组中第一个和后续消息的组状态信息(group status

information)必须进行如下设定:

第一条消息设为 AMGRP_FIRST_MSG_IN_GROUP

除第一和最后一条消息外,所有消息均设为 AMGRP_MIDDLEMSG_IN_GROUP

最后一条消息设为 AMGRP_LAST_MSG_IN_GRP

我们可以利用消息类的 setGroupStatus()实现上述目的。

messageObject.setGroupStatus(int groupStatus)

groupStatus可以为下面任何值:

AMGRP_MSG_NOT_IN_GROUP

AMGRP_FIRST_MSG_IN_GRP

AMGRP_MIDDLE_MSG_IN_GRP

Page 30: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

118

AMGRP_LAST_MSG_IN_GROUP

AMGRP_ONLY_MSG_IN_GROUP

如 果 AMGRP_FIRST_MSG_IN_GROUP 在 序 列 外 , 那 么 该 消 息 的 行 为 与

AMGRP_MIDDLE_MSG_IN_GRP相同。

提示:一旦应用程序开始发送在组中的消息,那么在尝试发送不在该组内的任何其他消

息之前,必须先发送完该组的消息。

4.9 模式的探索

在本节中,我们将给出实例,讨论如何才能利用 AMI、采用不同的编程模式构建应用程

序。

4.9.1 一对一或点到点 发送-遗忘

就发送-遗忘应用程序而言,必须创建以下对象:

会话

策略

发送者

消息

我们在本节中给出的程序样例将遵循如下逻辑流程:

创建会话库对象。

从会话库创建会话对象

从会话对象创建策略对象、消息对象和发送者对象

打开会话和发送者对象

将数据移植到消息对象

利用发送方法发送者对象上的消息对象进行发送

关闭发送者对象,而后关闭会话对象

尝试连接到队列管理器之前要做的第一件事是,通知 Java虚拟机(JVM)以包括MQSeries

AMI Java类。我们可利用例 4-20所显示的导入语句来实现这一目的。应记住,在将要

编译和运行应用程序的两个系统上,应在 CLASSPATH环境变量中包含 JAR文件。

Page 31: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

119

例 4-20 导入语句 import com.ibm.mq.amt.*;

一旦我们已经包括了 AMI JAR文件,那么下一步就是定义并初始化发送-遗忘应用程序

所需的对象。正如我们在前面提到的那样,当采用这种类型的模式时,我们需要会话库、

会话、发送者、消息和策略对象(每个对象都需要一个)。在此,我们建议对象名应当

具有描述性,这样就能便于我们记住它们的用途。

例 4-21显示定义并初始化对象的方法。

例 4-21 定义并初始化 private AmSessionFactory mySessionFactory = null; private AmSession mySession = null; private AmSender mySender = null; private AmMessage mySendMSG = null; private AmPolicy myPolicy = null;

创建类的实例时,有必要分配内存以储存数据。当我们开始定义实例时,编译器被告知:

在类中将使用具有某个名称的变量。因此,还有必要为变量分配内存。我们可以使用新

运算符来完成这一工作。我们需要为会话库对象分配内存。

例 4-22显示了如何定义会话库对象 mySessionFactory(我们在例 4-21中对其做了定

义)的参照。

例 4-22 定义参照 mySessionFactory = new AmSessionFactory();

一旦为会话库分配了内存,我们就可以创建该类型模式所需的其余对象了。我们将利用

createSession()、createPolicy()、createSender()和 createMessage()方法。例 4-

23显示了如何创建下列对象:

称为 SAMPLE_SESSION_NAME的会话对象

称为 SAMPLE_POLICY_NAME的策略对象

称为 SAMPLE_SENDER_NAME的发送者对象

称为 SAMPLE_MESSAGE_NAME的消息对象

例 4-24 创建对象样例 mySession = mySessionFactory.createSession(“SAMPLE_SESSION_NAME”); myPolicy = mySession.createPolicy(“SAMPLE_POLICY_NAME”); mySender = mySession.createSender(“SAMPLE_SENDER_NAME”);

Page 32: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

120

mySendMSG = mySession.createMessage(“SAMPLE_MESSAGE_NAME”);

创建对象之后,必须打开会话和发送者对象。

例 4-24显示了打开会话对象 mySession和发送者对象 mySender的方法。

例 4-24 打开对象 mySession.open(myPolicy); mySender.open(myPolicy);

打开对象后,我们可以利用 send()方法发送消息。正如我们在第 4.5.3节《基本操作》

(见本书第 109页)中所提到的那样,消息内容总是以字节形式(Java的本身形式)发

送,因此我们必须用 getBytes()方法(Java的本身方法)在发送消息之前将其转化为

字节数组。一旦转化消息后,就需要采用发送者类的 writeBytes()方法将其写入消息

对象。例 4-25显示了如何利用编码字符集标识符 819准备并发送消息。

例 4-25 准备并发送 String sampleMessage = new String("Sample message"); mySendMSG.setCCSID(819); mySendMSG.writeBytes(sampleMessage.getBytes()); mySender.send(mySendMSG, myPolicy);

如果不再发送更多的消息,必须发出发送者类和会话类的 close()方法以关闭对象。

例 4-26显示了如何关闭我们在例 4-24(见本书第 120页)中打开的对象。

例 4-26 关闭对象 mySender.close(myPolicy); mySession.close(myPolicy);

请求/回复

就请求/回复应用程序而言,必须创建以下对象:

会话

策略

发送者

接收者

消息

我们在本节中要讨论的程序样例将遵循以下逻辑:

Page 33: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

121

创建会话库对象。

从会话库对象创建会话对象。

从会话对象创建策略对象、待发送的消息对象、要接收的消息对象、发送者对象

和接收者对象。

打开会话对象、接收者对象和发送者对象。

利用 writeBytes()方法将数据移植到待发送的消息对象中。

发送待发送的消息对象,在发送对象上利用发送方法,将接收者对象作为响应服

务来进行传递。

在接收者对象上发出接收之前,在策略对象中将 waitTime设置为两秒钟。

用 readBytes方法提取并显示用来接收消息对象的数据,使用待发送的消息作为选

择消息。

关闭接收者、发送者和会话对象。

我们在尝试连接到队列管理器之前必须要做的第一件事是通知 Java虚拟机(JVM)以包

括MQSeries AMI Java classes。我们可以利用例 4-27中所显示的导入语句来实现这一

目的。应记住,在将要编译和运行应用程序的两个系统上,应在 CLASSPATH环境变量

中包含 JAR文件。

例 4-27 导入语句 import com.ibm.mq.amt.*;

一旦我们已将 AMI JAR文件包括在内,那么下一步就将定义并初始化请求/回复应用程

序所需的对象。正如我们在前面所提到的那样,在这种类型的模式中,我们需要会话库、

会话对象、发送者对象、接收者对象、两个消息对象(一个用于发送消息,另一个则用

于回复消息),以及策略对象。我们建议对象名应当具有描述性,这样能便于我们记住

其用途。

例 4-28显示了定义并初始化对象的方法。

例 4-28 定义并初始化 private AmSessionFactory mySessionFactory = null; private AmSession mySession = null; private AmSender mySender = null; private AmReceiver myReceiver = null; private AmMessage mySendMSG = null; private AmMessage myReceiveMSG = null;

Page 34: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

122

private AmPolicy myPolicy = null;

在创建类的实例时,应当分配内存以储存数据。当我们在开始定义实例时,编译器被告

知:在类中将使用具有某个名称的变量。因此,还应当为变量分配内存。我们可以用新

运算符来完成这步工作。应为会话库对象分配内存。例 4-29显示了如何定义会话库对

象 mySessionFactory(我们在例 4-28中对其做了定义)的参照。

例 4-29 定义参照 mySessionFactory = new AmSessionFactory();

一旦将内存分配给会话库,就可以创建此类型模式所需的其余对象了。我们将利用

createSession、createPolicy、createSender、createReceiver,以及 createMessage方法。

例 4-30显示了如何创建以下对象:

称为 SMAPLE_SESSION_NAME的会话对象

称为 SAMPLE_POLICY_NAME的策略对象

称为 SAMPLE_SENDER_NAME的发送者对象

称为 SAMPLE_RECEIVER_NAME的接收者对象

两个消息对象: SAMPLE_SEND_MESSAGE_NAME(用于发送消息)和

SAMPLE_RECEIVE_MESSAGE_NAME(用于接收回复)

例 4-30 创建对象 mySession = mySessionFactory.createSession(“SAMPLE_SESSION_NAME”); myPolicy = mySession.createPolicy(“SAMPLE_POLICY_NAME”); mySender = mySession.createSender(“SAMPLE_SENDER_NAME”); myReceiver = mySession.createReceiver(“SAMPLE_RECEIVER_NAME”); mySendMSG = mySession.createMessage(“SAMPLE_SEND_MESSAGE_NAME”); myReceiveMSG = mySession.createMessage(“SAMPLE_RECEIVE_MESSAGE_NAME”);

创建对象之后,必须打开会话、发送者和接收者对象。例 4-31显示了如何打开会话对

象 mySession、发送者对象 mySender,以及接收者对象 myReceiver。

例 4-31 打开对象 mySession.open(myPolicy); mySender.open(myPolicy); myReceiver.open(myPolicy);

Page 35: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

123

打开对象后,我们就可以利用 send()方法发送消息了。正如我们在第 4.5.3 节《基本

操作》(见本书第 109 页)所提到的那样,总以字节形式(Java 的本身形式)发送消息

内容,因此我们在发送消息前必须使用 getBytes()方法(Java的本身方法)来将消息

转化为字节数组。一旦转化消息,就应当采用发送者类的 writeBytes()方法将其写入

消息对象。

例 4-32显示了如何利用编码字符集标识符 819准备并发送消息。请注意,这次我们将

发送接收者对象,以表明我们需要获得回复消息。

例 4-32 准备并发送 String sampleMessage = "Sample message"; mySendMSG.setCCSID(819); mySendMSG.writeBytes(sampleMessage.getBytes()); mySender.send(mySendMSG, myReceiver, myPolicy);

为了确定回复的等待时间,我们必须利用策略类的 setWaitTime()方法。一旦消息到

达之后,就要使用接收者类的 receive()方法。为了读取消息对象的内容,我们必须使

用接收者类的 readBytes()方法。

例 4-33显示了如何接收消息。这一例子也显示了如何将等待时间设置为两秒钟(2000

毫秒)。

例 4-33 接收消息 myPolicy.setWaitTime(2000); mySendMSG.setCCSID(AMCP_819); myReceiver.receive(myReceiveMSG, mySendMSG, myPolicy); replyMessage = new String(myReceiveMSG.readBytes(myReceiveMSG.getDataLength()),"ISO8859_1");

如果不再发送新消息,那么必须发出发送者、接收者和会话类的 close()方法来关闭

对象。可以省略发送者和接收者类的 close()方法,因为一旦关闭了会话对象,其余

参照都会无效。例 4-34显示了如何关闭例 4-31中打开的对象。

例 4-34 关闭对象 mySender.close(myPolicy); myReceiver.close(myPolicy); mySession.close(myPolicy);

Page 36: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

124

4.9.2 发布/预订 发布者

就发布者应用程序而言,我们必须创建以下对象:

会话

策略

发布者

接收者

两个消息对象(一个用于将要发布的消息,另一个则用于响应)

我们在本节中要讨论的发布者程序样例将遵循以下逻辑:

创建会话库对象。

从会话库对象创建会话对象。

从会话对象创建策略对象、发布内容的消息对象,以及发布者对象。

打开会话对象和发布者。

利用 addTopic方法向发布消息添加主题。

从主题中进行选择,并利用 writeBytes方法将数据写入将发出的消息中。

调用发布者对象的发布方法以发布信息。

重置发布消息。

等待两秒钟。

检索由代理生成的发布回复

重复进行前六步,直至达到在开始确定的最大发布数量。

关闭发布者和会话对象。

我们在尝试连接到队列管理器之前必须要做的第一件事是通知 Java虚拟机(JVM)以包

括MQSeries AMI Java classes。我们可以利用例 4-35中所显示的导入语句来实现这一

目的。应记住,在将要编译和运行应用程序的两个系统上,应在 CLASSPATH环境变量

中包含 JAR文件。

Page 37: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

125

例 4-35 导入语句 import com.ibm.mq.amt.*;

一旦我们已经包括了 AMI JAR文件,下一步就要定义并初始化发布/预订应用程序所需

的对象。正如我们在前面提到的那样,当采用这种类型的模式时,需要会话库、会话对

象、发布者对象、两个消息对象(一个用于将发布的消息,另一个则用于响应)和策略

对象。我们建议,对象名应当具有描述性,这样就能便于我们记住它们的用途。

例 4-36显示了如何定义并初始化对象。

例 4-36 定义并初始化对象 private AmSessionFactory mySessionFactory = null; private AmSession mySession = null; private AmPublisher myPublisher = null; private AmMessage mySendMSG = null; private AmMessage myRespMSG = null; private AmPolicy myPolicy = null; private AmReceiver myRespReceiver = null;

在创建类的实例时,应当分配内存以储存数据。当我们开始定义实例时,编译器被告知:

在类中将使用具有某个名称的变量。因此,还应当为变量分配内存。我们可以用新运算

符来完成这步工作。应当为会话库对象分配内存。例 4-37显示了如何定义会话库对象

mySessionFactory(我们在例 4-36中对其做了定义)的参照。

例 4-37 定义参照 mySessionFactory = new AmSessionFactory();

一旦为内存分配了会话库,我们就可以创建此类型模式所需的其余对象了。我们将采用

createSession()、createPolicy()、createSender()、createReceiver(),以及 createMessage

()方法。

例 4-38显示了如何创建以下对象:

称为 SMAPLE_SESSION_NAME的会话对象

称为 SAMPLE_POLICY_NAME的策略对象

称为 SAMPLE_PUBLISHER_NAME的发布者对象

称为 SAMPLE_RESPONSE_NAME的接收者对象

Page 38: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

126

两个消息对象: SAMPLE_MESSAGE_NAME(用于将要发布的消息)和

SAMPLE_RESP_MESSAGE_NAME(用于响应)

例 4-38 创建对象 mySession = mySessionFactory.createSession(“SAMPLE_SESSION_NAME”); myPolicy = mySession.createPolicy(“SAMPLE_POLICY_NAME”); myPublisher = mySession.createPublisher(“SAMPLE_PUBLISHER_NAME”); myRespReceiver = mySession.createReceiver(“SAMPLE_RESPONSE_NAME”); mySendMSG = mySession.createMessage(“SAMPLE_MESSAGE_NAME”); myRespMSG = mySession.createMessage(“SAMPLE_RESP_MESSAGE_NAME”);

创建对象之后,必须打开会话、发布者和接收者对象。

例 4-39显示了如何打开会话对象 mySession、发布者对象 myPublisher,以及接收者对

象 myRespReceiver。

例 4-39 打开对象 mySession.open(myPolicy); myPublisher.open(myPolicy); myRespReceiver.open(myPolicy);

下一步就是向消息对象添加主题。我们利用消息对象的 addTopic()方法来实现这一目

的。例 4-40显示了如何向例 4-38中创建的发布者对象添加“天气”主题。而后设置

消息属性 CCSID,并将消息字符串转换为确定编码页的字节,从而向消息对象

mySendMSG添加数据。

一旦数据从字符串转化为字节数组,就会发布消息对象的内容。在发布调用时,数据与

接收者对象 myRespReceiver一起发送,目的是获得代理发送的承认。

例 4-40 添加主题 String sunny = "SUNNY again"; String showers = "WIND and SCATTERED showers"; String rain = "HEAVY RAIN"; String outlook[] = {sunny, showers, rain}; for (int i = 0, j = 0; i < SAMPLE_MAX_PUBLICATIONS; i++, j++) { try { mySendMSG.addTopic(“Weather”); if (j == 3)

Page 39: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

127

{ j = 0; } String sampleMessage = new String(outlook[j]); mySendMSG.setCCSID(819); mySendMSG.writeBytes(sampleMessage.getBytes("ISO8859_1")); myPublisher.publish(mySendMSG, myRespReceiver, myPolicy); myRespReceiver.receive(myRespMSG, mySendMSG, myPolicy); } }

如果不再发布新消息,那么必须发出发布者、接收者和会话类的 close()方法来关闭

对象。可以省略发布者和接收者类的 close()方法,因为一旦关闭会话对象,其他参

照都将无效。

例 4-41显示了如何关闭例 4-39中打开的对象。

例 4-41 关闭对象 myPublisher.close(myPolicy); myReceiver.close(myPolicy); mySession.close(myPolicy);

预订者

就预订者应用程序而言,我们应当创建以下对象:

会话

策略

预订者

两个消息对象(一个用于发送预订信息,另一个则用于接受发布信息)

我们在本节中要讨论的预订者程序样例将遵循以下逻辑:

创建会话库对象。

从会话库创建会话对象。

从会话创建策略对象、用于预订的消息对象、接收发布信息的消息对象,以及预

订者对象。

打开会话对象和预订者对象。

用 addTopic方法向预订信息消息添加主题,并将其传递到预订者类的预订方法上。

Page 40: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

128

调用预订者类的接收方法。

利用消息对象的 readBytes方法读取并显示将流入消息中的发布数据。

重置用于接收发布的消息对象。

重复进行以上三步骤,直至达到事先确定的发布信息最大数量为止。

取消主题预订。

关闭预订者和会话对象。

我们在尝试连接到队列管理器之前必须要做的第一件事是通知 Java虚拟机(JVM)以包

括MQSeries AMI Java classes。我们可以利用例 4-42中所显示的导入语句来实现这一

目的。应记住,在将要编译和运行应用程序的两个系统上,应在 CLASSPATH环境变量

中包含 JAR文件。

例 4-42 导入 import com.ibm.mq.amt.*;

一旦我们已经包括了 AMI JAR文件,那么下一步就是定义并初始化预订者应用程序所

需的对象。正如我们在前面提到的那样,当采用这种类型的模式时,我们需要会话库、

会话对象、预订者对象、两个消息对象(一个用于发送预订信息,另一个用于接收发布

信息),以及策略对象。我们建议,对象名应当具有描述性,这样便于我们记住它们的

用途。

例 4-43显示了如何定义并初始化对象。

例 4-43 定义并初始化 private AmSessionFactory mySessionFactory = null; private AmSession mySession = null; private AmSubscriber mySubscriber = null; private AmMessage mySendMSG = null; private AmMessage myReceiveMSG = null; private AmPolicy myPolicy = null;

在创建类的实例时,应当分配内存以储存数据。当我们开始定义实例时,编译器被告知:

将在类中使用具有某个名称的变量。因此,还应当为变量分配内存。我们可以用新运算

符来完成这步工作。我们应当为会话库对象分配内存。例 4-44显示了如何定义会话库

对象 mySessionFactory(我们在例 4-43中对其做了定义)的参照。

Page 41: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

129

例 4-44 定义参照 mySessionFactory = new AmSessionFactory();

一旦为会话库分配了内存,我们就可以创建此类型模式所需的其余对象了。我们将利用

createSession、createPolicy、createSender,以及 createMessage方法。

例 4-45 显示了创建以下对象的方法:

称为 SMAPLE_SESSION_NAME的会话对象;

称为 SAMPLE_POLICY_NAME的策略对象;

称为 SAMPLE_SUBSCRIBER_NAME的预订者对象;

称为 SAMPLE_RESPONSE_NAME的接收者对象;

两个消息对象:一个称为 SAMPLE_RECEIVE_MESSAGE_NAME(用于接收发布

信息),另一个称为 SAMPLE_SEND_MESSAGE_NAME(用于发送预订请求)

例 4-45 创建对象 mySessionFactory = new AmSessionFactory(); mySession = mySessionFactory.createSession(“SAMPLE_SESSION_NAME”); myPolicy = mySession.createPolicy(“SAMPLE_POLICY_NAME”); mySubscriber = mySession.createSubscriber(“SAMPLE_SUBSCRIBER_NAME”); myReceiveMSG = mySession.createMessage(“SAMPLE_RECEIVE_MESSAGE_NAME”); mySendMSG = mySession.createMessage(“SAMPLE_SEND_MESSAGE_NAME”);

一旦创建了对象,就必须打开会话和预订者对象。

例 4-46显示了如何打开会话对象 mySession和预订者对象 mySubscriber。

例 4-46 打开会话 mySession.open(myPolicy); mySubscriber.open(myPolicy);

例 4-47显示了如何将消息对象重置为初始状态。获取发布信息之前,必须利用消息类

的 addTopic()方法将主题名添加到消息对象中。一旦主题添加到了 mySendMSG中,

我们将利用预订者对象 mySubscriber的 subscribe()方法来发送预订请求。

例 4-47 重置消息对象 String topic = "Weather"; Try

Page 42: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

130

{ mySendMSG.reset(); mySendMSG.addTopic(topic); mySubscriber.subscribe(mySendMSG, myPolicy); }

现在,我们需要接收主题为天气的一些发布信息。为了实现这一目的,我们要用到

mySubscriber的 receive()调用。一旦接受了发布信息,我们就必须利用接收者对象的

readBytes()方法将其转换为字节数组。

例4-48显示了如何将消息数据从字符串转化为字节数组。该消息随后将显示在屏幕上,

也将重置消息对象。

例 4-48 转化消息 for (i = 0; i < SAMPLE_MAX_PUBLICATIONS; i++) { try { mySubscriber.receive(myReceiveMSG, myPolicy); String myRequest = new String(myReceiveMSG.readBytes(myReceiveMSG.getDataLength()),"ISO8859_1"); System.out.println(myRequest); myReceiveMSG.reset(); } }

在例 4-49中,我们采用预订者对象 mySubscriber的 unsubscribe()方法向代理发送消

息,取消预订注册。

例 4-49 取消注册 String topic = "Weather"; try { mySendMSG.reset(); mySendMSG.addTopic(topic); // -------------------------------------------------------------- // Send the request.(发送请求) //No response is expected so no receiver object is passed.(不需要响应,因而也不传递接收者对象) // -------------------------------------------------------------- mySubscriber.unsubscribe(mySendMSG, myPolicy); }

Page 43: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

131

如果不再接收新消息,那么必须发出预订者和会话类的 close()方法来关闭对象。可

以省略预订者类的 close()方法,因为一旦关闭会话对象,其他的参照都将无效。

例 4-50显示了如何关闭例 4-46中(见本书第 129页)打开的对象。

例 4-50 关闭对象 mySubscriber.close(myPolicy); mySession.close(myPolicy);

在本章中,我们看到了应用程序设计人员可以利用 AMI 来构建程序的方法,而无需了

解MQSeries消息队列接口的所有细节。

Page 44: 用AMI编程 - IBM · 89 4 用ami编程 本章将概括介绍应用程序消息接口,讲解什么是ami 以及如何应用ami。如欲了解更 多有关信息,请参见《应用程序消息接口参考》编号:sc34-5604。

132