在编写代码实现发送和接收消息之前,先对MQ常用的一些概念做一下解释。
管理器
管理器是MQ系统中最上层的一个概念,由它为我们提供基于队列的消息服务队列
连接通道:
通道是MQ系统中队列管理器之间传递消息的管道,它是建立在物理的网络连接之上的一个逻辑概念
队列:
队列是消息的安全存放地,队列存储消息直到它被应用程序处理
消息:
在MQ中,我们把应用程序交由MQ传输的数据定义为消息,我们可以定义消息的内容并对消息进行广义的理解,比如:用户的各种类型的数据文件,某个应用向其它应用发出的处理请求等都可以作为消息,消息有两部分组成,消息描述符、消息体。
以大家熟悉的知识文档为例,
我将知识文档消息分为以下2类,并使用不同的队列存放:
1、"主文档消息",代表知识文档的主要内容概括,包括主题,创建人,创建时间,主要内容,以及文档权限控制等信息。
主文档消息以XML的格式表示。规范如下:
<root>
<head>
<bizid>0003</bizid>
</head>
<kmdoc>
<ip>10.x.x.x</ip>
<from>XXX 系统</from>
<id>2343</id>
<subject>关于XXXX 的报告</subject>
<creator> uid=xuhb0309,cn=employees,dc=.....</creator>
<created>20081111 21:00:00</created>
<docauthor> uid=xuhb0309,cn=employees,dc=.....</docauthor>
<keywords>关键字1</keywords>
<useyears>1</useyears>
<description>描述文容<?p>?测试</description>
<context>正文内容<?p>?测试正文内容<?b>?</context>
<printcopy>0</printcopy>
<readers>部门、授权组或者人员在LDAP 中的dn,用半角分号分隔</readers>
<authors>部门、授权组或者人员在LDAP 中的dn,用半角分号分隔</authors>
<attcopy>1</attcopy>
<copyusers></copyusers>
<attprint>0</attprint>
<printusers>部门、授权组或者人员在LDAP 中的dn</printusers>
<attdownload>0</attdownload>
<dwldusers>部门、授权组或者人员在LDAP 中的dn </dwldusers>
<attachments>
<attachment>
<id>att200911200002</id>
<name>只是一个附件而已.doc</name>
</attachment>
.................................
</attachments>
</kmdoc>
.................................
</root>
2、"附件消息",包含附件,主文档消息和附件消息是一对多的关系,即一个主文档消息可以对应多个附件消息。附件消息和主文档的关联通过主文档消息的attmentment的ID和name子节点,其中id节点内容是附件消息的messageIds属性内容,name节点内容是附件的文件名。
附件传送方式过程如下:
l 各应用系统发送文件:
将文件转换成BytesMessage的形式,发送到消息队列。消息的 messageFlags字段需要包括值 MQC.MQMF_MSG_IN_GROUP。如果文件大小超过设定的大小限制(MaxMsgLength),对消息进行分段 ,最后一个消息分段的messageFlags字段需要包括值: MQC.MQMF_LAST_MSG_IN_GROUP
l 知识中心接收文件:
知识中心会从接收队列检索所有分段,返回完整的文件。
发送/接收主文档消息和发送/接收附件消息同理,因为发送xxx.xml文件也不过是发送一种文件。
写代码前需要引入com.ibm.mq.jar | connector.jar 这2个文件在MQ的服务器上找的到。
以下是发送文件的代码片段
final int BUFFER_LEN = 1024*1024*3;
String hostname = "127.0.0.1";
String channel = "channel1";
int port = 1416;
String mqManager = "qm1";
String mqQname1 = "q1";
MQEnvironment.addConnectionPoolToken();
MQEnvironment.hostname = hostname;
MQEnvironment.channel = channel;
MQEnvironment.CCSID = 1381;
MQEnvironment.port = port;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
MQQueueManager qMgr = new MQQueueManager(mqManager);
int openOptions = MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING;
MQQueue mqQ = qMgr.accessQueue(mqQname1,openOptions);
String filePath = "d://文本文档.txt";
String filename = filePath.replace('//','/');
filename = filename.substring ( filename.lastIndexOf('/')+1,filename.length());
MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options = pmo.options + MQC.MQPMO_LOGICAL_ORDER;
pmo.options = pmo.options + MQC.MQPMRF_GROUP_ID;
MQMessage outMsg = new MQMessage();
/* 设置消息标记,表示该消息属于组 */
outMsg.messageFlags = MQC.MQMF_MSG_IN_GROUP;
FileInputStream fis = new FileInputStream(new File(filePath));
byte buffer[] = new byte[BUFFER_LEN];
int count = 0;
while (true) {
count = fis.read(buffer, 0, BUFFER_LEN);
if(count == -1){
break;
}
outMsg.write(buffer,0,count);
if(count < BUFFER_LEN){
outMsg.messageFlags = MQC.MQMF_LAST_MSG_IN_GROUP;
}
mqQ.put(outMsg, pmo);
outMsg.clearMessage();
}
fis.close();
qMgr.commit();
mqQ.close();
qMgr.disconnect();
以下是接收文件的代码片段
String hostname = "127.0.0.1";
String channel = "channel1";
int port = 1416;
String mqManager = "qm1";
String mqQname1 = "q1";
MQEnvironment.addConnectionPoolToken();
MQEnvironment.hostname = hostname;
MQEnvironment.channel = channel;
MQEnvironment.CCSID = 1381;
MQEnvironment.port = port;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
MQQueueManager qMgr = new MQQueueManager(mqManager);
int openOptions = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT;
MQQueue mqQ = qMgr.accessQueue(mqQname1,openOptions);
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.options = gmo.options + MQC.MQGMO_SYNCPOINT;
gmo.options = gmo.options + MQC.MQGMO_WAIT;
gmo.waitInterval = 5000;
gmo.options = gmo.options + MQC.MQGMO_ALL_MSGS_AVAILABLE;
gmo.options = gmo.options + MQC.MQGMO_LOGICAL_ORDER;
gmo.matchOptions = MQC.MQMO_MATCH_GROUP_ID;
FileOutputStream fos = null;
/* 处理组消息*/
try {
while(true) {
/* 创建消息缓冲*/
MQMessage inMsg = new MQMessage();
while (true) {
mqQ.get(inMsg, gmo);
String filename = "这里省略部分去取文件名的代码";
System.out.println(filename); //文件名
if (fos==null)
fos = new FileOutputStream(new File("e:/" + filename)) ;
int msgLength = inMsg.getMessageLength();
byte[] buffer = new byte[msgLength];
inMsg.readFully(buffer);
fos.write(buffer, 0, msgLength);
char x = gmo.groupStatus;
/*查看是否是最后消息标*/
if (x == MQC.MQGS_LAST_MSG_IN_GROUP) {
System.out.println("last in group");
if(fos!=null)fos.close();
fos=null;
break;
}
inMsg.clearMessage();
}
qMgr.commit();
}
}catch(MQException e){
if (e.reasonCode != 2033)
throw e;
}
mqQ.close();
qMgr.disconnect();