1、如果实际的打开选项不符合在队列上进行操作的要求的话,那么ImqQueue对象就会关闭并重新打开队列。在某些情况下,根据被打开队列的类型,将会导致一些额外的开销或某些问题。为了避免自动关闭和重新打开队列,我们必须利用ImqObject 类的openFor 方法或setOpenOptions 直接设置打开选项。我们也可以利用ImqObject 类的打开方法显式打开队列,但是如果打开选项已经指定的话,那么较之于这种接口提供的隐式打开,它并不能提供什么重大优势。pqueue.setOpenOptions(MQOO_OUTPUT | MQOO_INPUT_SHARED);pqueue.openFor(M
2、QOO_OUTPUT | MQOO_INPUT_SHARED);openFor 方法不断添加指定的打开选项到实际分配给对象的选项。ImqQueue 对象的默认打开选项是MQOO_INQUIRE。 打开动态队列动态队列不能通过重新打开方式自动关闭,因为对动态队列进行关闭操作会删除该队列。因此,打开动态队列时,我们必须指定打开选项。队列模型的名由ImqObject 类的setName 方法指定,动态队列名或其前缀可以用ImqQueue 类的setDynamicQueueName 方法确定。动态队列的实际名可以在队列打开后用dynamicQueueName 方法获得。pqueue.setDynami
3、cQueueName(dynamicqueuename); 打开分布列表分布列表由ImqDistributionList 类进行管理,它继承自ImqQueue 类。可以利用ImqQueue 类的setDistributionReference 方法将任意数量的ImqQueue 对象和一个ImqDistributionList 对象关联起来。在打开分布列表之前,相关联的队列必须分配到队列名和包含队列的队列管理器,下面提供了一个打开分布列表的例子:ImqDistributionList dlist;ImqQueue queueA, queueB;ImqString queueManagerName
4、(pmanager.name();queueA.setConnectionReference(pmanager);queueB.setConnectionReference(pmanager);queueA.setName(queuename1);queueB.setName(queuename2);queueA.setQueueManagerName( queueManagerName);queueB.setQueueManagerName( queueManagerName);queueA.setDistributionListReference(dlist);queueB.setDist
5、ributionListReference(dlist);一旦设置好分布列表的队列,就可以向其他任何ImqQueue 对象一样来打开分布列表并对其进行操作。11.5.3 关闭WebSphere MQ对象WebSphere MQ 对象在删除与其相应的ImqObject 后即会自动关闭。11.5.4 断开与队列管理器的连接当删除ImqQueueManager 对象后,将隐式执行断开连接操作。11.5.5 消息放入队列我们可以利用ImqQueue 类的放置方法将消息放入ImqQueue 或ImqDistributionList。放置方法提供两种接口:ImqBoolean put(ImqMessage
6、 & msg); msg, ImqPutMessageOptions & pmo);消息数据由ImqMessage 类管理。ImqMessage 类继承自ImqMessageTracker 类(它包括MQMD 数据结构)和ImqCache 类(它处理消息数据缓冲区)。我们可以利用ImqMessageTracker 类的setMessageId 方法来设置消息身份。ImqMessage msg;msg.setMessageId(msgId);同样,我们也可以利用某些方法来访问关联性ID 和组ID。我们必须用ImqBinary 类来创建messageId、correlationId 和groupI
7、d。该类包括用于MQI的BYTExx 数据类型,它提供某些进行基本操作的方法。下例显示了如何利用ImqBinary 来创建二进制对象。ImqBinary correlationId ;MQBYTE24 byteId =“BYTEID1234”;correlationId.set(byteId,sizeof(byteId );准备消息数据该API 与MQI API 的不同之处在于准备和处理消息数据的方法不同。在MQI 中,从分配正确的缓冲区到储存数据,再到读取消息时处理消息中不同的可能标题,消息完全由应用程序管理。在C+ API 中,添加了一些缓冲功能,而且缓冲区由ImqCache 对象管理。缓
8、冲区通过继承与每个消息(ImqMessage 对象)相关联。默认情况下,缓冲区由ImqCache 自动提供,或者也可以由应用程序利用以下任何一种ImqCache 对象方法来提供: useEmptyBuffer:这种方法允许应用程序分配一个固定长度的空白缓冲区给ImqMesage 对象。如果没有分配实际消息长度的话,那么会将消息长度自动设置为零,而且缓冲区也将是空的。char pszBuffer24=“Hello World”;msg.useEmptyBuffer(pszBuffer, sizeof(pszBuffer);msg.setFormat(MQFMT_STRING);msg.setMe
9、ssageLength(12);或char pszBuffer12;useFullBuffer:这种方法允许应用程序分配一个已经准备好的消息缓冲区给ImqMessage 对象。该缓冲区将不是空的,消息长度也将被设为方法调用所提供的长度。char pszBuffer =“Hello world”;msg.useFullBuffer(pszBuffer, sizeof(pszBuffer);消息缓冲区可以重复使用,我们也可以利用ImqCache 类的setMessegeLength 方法来设置消息长度,因此发送字节的数量也各不相同。由应用程序提供消息缓冲区的优势在于无需进行数据拷贝,因为数据可以直
10、接在缓冲区中准备。为了将ImqCache 再设为自动的缓冲区,应用程序可以用空缓冲区指针和零(0)长度调用useEmptyBuffer。当自动提供缓冲区时,缓冲区随着消息的增长而增长。这为准备消息前却不知道消息长度提供了更多的灵活性。可以利用ImqCache 写入方法将消息(数据)拷贝到缓冲区中。msg.write(12, “Hello world”);我们可以利用ImqMessage 的writeItem 方法将项目拷贝到缓冲区中。比方说,您可能希望向消息添加一个死信标题,并将其放入死信队列中。下例显示了如何创建一个ImqDeadLetterHeader 并将其插入现有消息的开始部分。Imq
11、DeadLetterHeader header;header.setDestinationQueueManagerName(pmanager.name();header.setDestinationQueueName(pqueue.name();header.setPutApplicationName(/*?*/);header.setPutApplicationType(/*?header.setPutDate(/* TODAY*/);header.setPutTime(/* NOW*/);header.setDeadLetterReasonCode(/* REASON*/);msg.wri
12、teItem(header);可以在放置方法中使用更多选项,正如ImqQueue 类的放置方法提供了两种接口。在将消息放到队列上时,必须经常指定更多的选项。我们可以用以ImqPutMessageOptions对象为形式的第二个参数调用放置方法来指定这些选项。ImqPutMessageOptions 类包括MQPMO 数据结构,它允许应用程序指定更多的选项,如同步点控制或消息上下文。下例显示了如何启动并设置同步点选项。这将启动本地队列管理器事务处理,我们可以利用ImqQueueManager 类的提交或回滚方法来结束它。ImqPutMessageOptions pmo;pmo.setSyncPo
13、intParticipation(TRUE);pqueue.put(msg, pmo);如欲了解ImqQueue 类可用选项的更多信息,请参见Using C+手册。11.5.6从队列获取消息我们可以利用该类提供的获取方法从ImqQueue 对象上获取消息。ImqQueue 获取方法提供四种接口:ImqBoolean get(ImqMessage & msg, ImqGetMessageOptions & options); options,const size_t buffer-size); msg, const size_t buffer-size);在方法调用之后,消息信息会包含在ImqM
14、essage 对象中。缺省情况下,消息缓冲区由系统提供,可以利用dataPointer 或bufferPointer 方法获得。消息数据长度可以利用ImqCache 类的dataLength 方法获得。pqueue.get(msg);char *pszDataPointer = msg.dataPointer();int iDataLength = msg.dataLength(); 注意:在每次获取方法调用之后,数据缓冲区的物理位置可能发生改变,因此我们建议不要使用实际的缓冲区指针来访问数据。我们应当利用dataPointer 或bufferPointer 方法来重新分配数据指针。如果应用程
15、序希望提供固定长度的缓冲区来接收消息数据的话,那么我们可以在利用ImqQueue 的获取方法前使用ImqCache 的useEmptyBuffer 方法。给定缓冲区的长度将限制消息长度,因此在应用程序设计中必须考虑到长消息的情况。char pszBufferBUFFER_LENGTH;pqueue.useEmptyBuffer(pszBuffer, BUFFER_LENGTH);在这种情况下,我们可以一直使用实际的缓冲区指针pszBuffer,但是我们还是建议采用dataPointer 方法以保证可移植性。读取消息数据一旦接收到消息,那么根据消息格式,消息数据可能是项目形式的,也可能是原始的用
16、户数据形式。但项目必须是分别连续处理的数据的各个部分。我们可以利用ImqMessage 的formatIs 来确保消息格式的有效性。如果消息格式代表着任何已知消息标题数据结构,那么我们可以利用ImqMessage 的readItem 方法从消息中获得结构。该API 具有三个实现定义的消息标题: 死信标题(ImqDeadLetterHeader class); IMS 桥标题(ImqIMSBridgeHeader); 参照标题(ImqReferenceHeader)。每个标题都对应于一个WebSphere MQ定义的消息格式。用户可以指定ImqItem 类来定义其他类型的格式。if (msg.f
17、ormatIs(MQFMT_DEAD_LETTER_HEADER) /*The readItem method must be called with the right class of object pointer*/if (msg.readItem(header) /*Perform the corresponding operation for this item type*/ 如果消息格式未知的话,那么正如前面所讲解过的那样,我们可以利用dataPointer 方法来直接访问消息数据。更多的获取方法选项ImqGetMessageOptions 类为消息接收过程提供了更多信息,如: 获
18、取操作的等待间隔; 匹配选项; 消息选项; 同步点参加; 组状态; 细分状态。我们可以利用ImqGetMessageOptions 的setOptions 方法来指定任何MQI 中可用的消息获取选项。其中MQGMO_WAIT 选项应用较多,它为要完成的获取操作提供了一个等待间隔。这样,如果期待的消息还未到达队列的话,那么获取方法在返回错误前会等待一定的时间,时间长度是用ImqGetMessageOptions 类的setWaitInterval 方法来指定。下例显示了如何用无限等待选项从队列获取消息。ImqGetMessageOptions gmo;gmo.setOptions(MQGMO_W
19、AIT);/*Set the wait interval to unlimited meaning that the get operation*/*will wait until one message appears in the queue.*/gmo.setWaitInterval(MQWI_UNLIMITED);pqueue.get(msg,gmo);从队列获取特定消息通过ImqMessageTracker 类中的消息属性的任意结合,我们可以确认特定的消息。 MessageId CorrelationId GroupId这些选项必须在获取方法调用中传递的ImqMessage 对象中指
20、定。ImqGetMessageOptions 类为应用程序提供了一种在指定消息查找过程中将使用什么选项的方法。gmo.setMatchOptions(MQMO_MATCH_MSG_ID);If (pqueue.get(msg,gmo) /*Perform any operation with this message*/如果一个以上的消息与给定标准相匹配,那么将返回这些消息中的第一个,并且获取方法的后续调用将提供所有消息的访问。如果找到了匹配的消息,消息对象信息在获取方法调用后将发生改变,否则函数会返回假。11.5.7浏览队列上的消息我们可以利用ImqQueue 获取方法浏览队列上的消息。必须
21、用MQOO_BROWSE 选项来打开ImqQueue 对象。我们可以用setOpenOptions 或openFor 方法来实现这一目的。pqueue.setOpenOptions(MQOO_BROWSE);pqueue.openFor(MQOO_BROWSE);在队列对象已被打开并用于浏览后,我们必须用以下选项调用ImqQueue 获取方法:MQGMO_BROWSE_FIRST 消息选项,如果您希望浏览光标位于符合ImqMessage 对象指定的标准的第一个消息处的话;MQGMO_BROWSE_NEXT 消息选项,如果您希望浏览光标移动到符合ImqMessage 对象指定的标准的下一个消息的
22、话。获取方法将返回ImqMessage 对象的更新版本,浏览光标也将指向当前消息的信息,并且当前消息不会从队列中删除。队列对象一旦打开, 浏览光标就会指向队列中的第一个消息, 因此MQGMO_BROWSE_NEXT 选项与MQGMO_BROWSE_FIRST 具有相同的行为。gmo.setOptions(MQGMO_BROWSE_NEXT | MQGMO_WAIT);/*Browsing all the messages in the queue in sequential order*/while (pqueue.get(msg,gmo) /*Perform some operation w
23、ith the message*/. /*The MessageId and CorrelationId must be set to null before the next get method call*/msg.setMessageId(MQMI_NONE);msg.setCorrelId(MQCI_NONE);可以按照物理顺序或逻辑顺序来浏览消息。根据队列的消息到达顺序(MsgDeliverySequence),物理排序可以是FIFO(先进/先出)排序或优先级内FIFO 排序。逻辑顺序就是说,即便另一个组中的任何消息在本组最后一条消息接收前出现,属于同一个组的消息仍将按照其在队列中的
24、正确位置顺序排列。为了浏览逻辑顺序的消息,我们在调用方法时必须指定MQGMO_LOGICAL_ORDER 选项。gmo.setOptions(MQGMO_BROWSE_NEXT | MQGMO_WAIT | MQGMO_LOGICAL_ORDER);11.5.8查询并设置对象属性 查询属性利用此种API,较之于采用MQI API 时的情况,查询并设定对象属性实在是相当直接的操作。这里,ImqObject 类提供了两种查询方法,可查询任何显示的整数或字符属性。ImqBoolean inquire(const MQLONG int-attr, MQLONG & value );ImqBoolean
25、 inquire(const MQLONG char-attr, char * & buffer, const size_t length);int-attr 和char-attr 参数将MQIA_*和MQCA_*指数赋予属性。整数对象属性值在值参数中返回,正如下面这段代码所显示的那样:MQLONG depth;pqueue.inquire(MQIA_CURRENT_Q_DEPTH, depth);printf(“The current queue depth is: %d“,depth);字符对象属性值在缓冲区参数中返回,正如下面这段代码所显示的那样:char qnameMQCA_Q_MGR
26、_NAME_LENGTH;pqueue.inquire(MQCA_Q_MGR_NAME, qname, MQCA_Q_MGR_NAME_LENGTH); %s“,qname);缓冲区必须足够大,以致于可以容纳属性值。缓冲区的长度必须在长度参数中指定。设置对象属性为了设置队列属性,ImqObject 提供了两种查询属性的方法。ImqBoolean set(const MQLONG int-attr, MQLONG & value);ImqBoolean set(const MQLONG char-attr, char * buffer, const size_t length);下面这段代码显示
27、了这些函数可能的用法:/*This instruction inhibits any put operation on any type of queue. */pqueue.set(MQIA_INHIBIT_PUT,MQQA_PUT_INHIBITED);/*This instruction inhibits any get operation on any local queue.*/pqueue.set(MQIA_INHIBIT_GET,MQQA_GET_INHIBITED);只有下面这些队列属性值可以利用上述函数进行调整:- MQIA_INHIBIT_PUT- MQCA_TRIGGER_DATA- MQIA_DIST_LISTS- MQIA_INHIBIT_GET- MQIA_TRIGGER_CONTROL- MQIA_TRIGGER_DEPTH
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1