版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
<!--一个博主专栏付费入口结束-->
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
<div id="content_views" class="markdown_views">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<h1 id="1-背景知识"><a name="t0"></a>1-背景知识</h1>
IBM MQ支持多种语言开发,本文主要是考虑Java应用开发,MQ提供了相关的Java类库,可以很方便集成到Java应用中。
IBM MQ Java相关类库允许Java应用直接与队列管理器交互,或者连接MQ服务器和客户端进行交互。
类库主要有两个,一个是MQ classes for Java,另一个是支持JMS标准的MQ classes for JMS。
由于是示例学习,本文主要尝试利用MQ classes for Java建立MQ简单应用,从MQ 8.0开始,类库是基于Java 7建立,因此需要Java 7以上运行时环境。
当然官方推荐使用JMS,因为最新的功能例如异步消费、自动重连等功能,都只在JMS中支持
开发有两种通信模式连接MQ:
客户端模式(client mode):应用作为客户端使用TCP/IP连接MQ服务器,应用可以部署在相同机器上或者不同机器上;
绑定模式(binding mode):通过JNI(Java Native Interface)直接连接MQ服务器,避免网络通信,性能更佳,必须和MQ服务器在相同机器上;
2-开发环境准备
2.1 开发环境
VMware Workstation 11.1.4
SuSE Linux Server x64 SP4 虚拟机
JDK 8.0
MQ 8.0安装包
2.2 安装
安装好虚拟机,SuSE Linux SP4,接下来安装MQ本地开发环境
**安装MQ相关组件**
# tar -xvf WSMQ_8.0_IFR_TRIAL_LNX_ON_X86_64_.tar.gz
# cd server
安装MQ运行时组件:
# rpm -ivh MQSeriesRuntime-8.0.0-2.x86_64.rpm
安装服务器组件:
# rpm -ivh MQSeriesServer-8.0.0-2.x86_64.rpm
安装MQ Java库:这里面提供MQ Java开发相关的类库
# rpm -ivh MQSeriesJava-8.0.0-2.x86_64.rpm
安装MQ JRE:java运行时用来运行MQ Java应用
# rpm -ivh MQSeriesJRE-8.0.0-2.x86_64.rpm
**安装JDK**
下载JDK压缩包,放入/home目录下
# cd /home
# tar xvfz jdk-8u102-linux-x64.tar.gz
# cd jdk1.8.0_102
# ./java -version
出错:
Error occurred during initialization of VM
Could not allocate metaspace: 1073741824 bytes
很明显内存空间不够导致,原虚拟机只有768MB内存,增加到2GB,然后重启虚拟机
# reboot
# cd /home/jdk1.8.0_102/bin
# ./java -version
# ./javac
提示安装成功
**配置MQ服务器**
# useradd mquser1 -u 3001
# passwd mquser1 设置密码为mqtest2016
# su - mqm
~ cd /opt/mqm/bin
设置mq环境变量
~ source setmqenv -s
创建队列管理器JAVA.QUEUE.MANAGER.1,并启动
~ crtmqm JAVA.QUEUE.MANAGER.1
~ strmqm JAVA.QUEUE.MANAGER.1
~ dspmq 查看所有队列管理器运行状态
启动脚本执行器,进行设置
~ runmqsc JAVA.QUEUE.MANAGER.1
输入:
DEFINE QLOCAL(QUEUE1) 创建本地队列QUEUE1
授权mquser1用户(id为3001)使用队列QUEUE1,其中PROFILE是对该条记录进行命名,PRINCIPAL指定特定用户,表明权限授权某用户。
SET AUTHREC PROFILE(QUEUE1) OBJTYPE(QUEUE) PRINCIPAL('mquser1') AUTHADD(PUT,GET)
授权用户mquser1可以连接队列管理器
SET AUTHREC OBJTYPE(QMGR) PRINCIPAL('mquser1') AUTHADD(CONNECT)
定义服务器连接通道
DEFINE CHANNEL(JAVA.CLIENT.CHANNEL1) CHLTYPE(SVRCONN) TRPTYPE(TCP)
授权MQ客户端可以连接上面定义的通道,通过ip地址和用户名方式授权
SET CHLAUTH(JAVA.CLIENT.CHANNEL1) TYPE(ADDRESSMAP) ADDRESS('127.0.0.1') MCAUSER('mquser1')
定义监听器,接受连接
DEFINE LISTENER(JAVA.CLIENT.LISTENER1) TRPTYPE(TCP) CONTROL(QMGR) PORT(1316)
启动:
START LISTENER(JAVA.CLIENT.LISTENER1)
结束:
end
**编写Java程序**
MQ Java应用主要需要包含两个Jar包:com.ibm.mq.allclient.jar 和 com.ibm.mq.traceControl.jar
在安装目录下/opt/mqm/java/lib
# cd /opt/mqm/java/lib
# java -java com.ibm.mq.allclient.jar 查看该jar详细信息
接下来可以用vim或者IDE编写程序
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
3-客户端模式进行连接
简单应用,读写本机队列,发送消息和读取消息,以客户端模式,利用TCP/IP进行通信
# cd /home/mq
# vim MQTest.java
输入以下内容:
import java.io.IOException;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.MQConstants;
public class MQTest {
public static void main(String[] args) throws MQException, IOException
{
//发送消息给队列
put();
//从队列读取消息
get();
}
static void put() throws MQException, IOException
{
//配置MQ服务器连接参数
MQEnvironment.hostname = "127.0.0.1";
MQEnvironment.port = 1316;
MQEnvironment.channel = "JAVA.CLIENT.CHANNEL1";
//设置应用名称,方便服务器MQ 查看应用连接
MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");
//创建实例,连接队列管理器
MQQueueManager queueManager = new MQQueueManager("JAVA.QUEUE.MANAGER.1");
//以可写的方式访问队列管理器已定义的队列QUEUE1,当然也可以创建队列
MQQueue putQueue = queueManager.accessQueue("QUEUE1", CMQC.MQOO_OUTPUT);
//新建并发送消息给队列
MQMessage myMessage = new MQMessage();
String name = "MePlusPlus's 博客";
myMessage.writeUTF(name);
//使用默认的消息选项
MQPutMessageOptions pmo = new MQPutMessageOptions();
//发送消息
putQueue.put(myMessage, pmo);
putQueue.close();
//断开连接
queueManager.disconnect();
}
static void get() throws MQException, IOException
{
//配置MQ服务器连接参数
MQEnvironment.hostname = "127.0.0.1";
MQEnvironment.port = 1316;
MQEnvironment.channel = "JAVA.CLIENT.CHANNEL1";
//设置应用名称,方便服务器MQ 查看应用连接
MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");
//创建实例,连接队列管理器
MQQueueManager queueManager = new MQQueueManager("JAVA.QUEUE.MANAGER.1");
//以可读的方式访问队列管理器已定义的队列QUEUE1
MQQueue getQueue = queueManager.accessQueue("QUEUE1", CMQC.MQOO_INPUT_AS_Q_DEF);
//从队列读取消息
MQMessage theMessage = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
getQueue.get(theMessage, gmo);
String name = theMessage.readUTF();
System.out.println(name);
getQueue.close();
//断开连接
queueManager.disconnect();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
编译:
# /home/jdk1.8.0_102/bin/javac -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar -Xlint:unchecked MQTest.java
运行:
# /home/jdk1.8.0_102/bin/java -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:/home/mq MQTest
**注意**
路径必须以冒号分割,windows下cp参数是分号分割,运行时必须加上MQText.class所在的目录/home/mq,否则提示
错误:找不到或者无法加载主类MQTest;
此外必须指明引用的jar文件完整路径,否则提示 java.lang.ClassNotFoundException:com.ibm.mq.MQException.
运行可能出错:
com.ibm.mq.MQQueueManager.<init>(MQQueueManager.java:675)
at MQTest.put(MQTest.java:35)
at MQTest.main(MQTest.java:18) Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2538;AMQ9204:
与主机 '127.0.0.1(1316)' 的连接被拒绝。
[1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2538;AMQ9213: 发生 'TCP' 的通信错误。
解决:明显是和MQ服务器通信问题,可能是MQ服务器没有启动
# telnet 127.0.0.1 1316 是否连通
# su - mqm
~ cd /opt/mqm/bin
~ dspmq 查看队列管理器状态,如果没有启动,启动它
~ source setmqenv -s
~ strmqm JAVA.QUEUE.MANAGER.1
错误代码:网上查明,是因为与MQ服务器连接错误导致,是因为用户权限问题
com.ibm.mq.MQException: MQJE001: 完成代码为 '2',原因为 '2035'
在MQTest.java文件中加入:(**以下两句不用加,这个不是用来验证连接的用户,具体分析见最后小结,这个是后面实验发现**)
MQEnvironment.userID = "myuser1";
MQEnvironment.password = "mqtest2016";
此外在官方文档上找到解决方法:为在队列管理器重新增加用户mquser1用户的权限,MQ Java类库用到了其它权限。
# su - mqm
~ cd /opt/mqm/bin
设置mq环境变量
~ source setmqenv -s
启动脚本执行器,进行设置
~ runmqsc JAVA.QUEUE.MANAGER.1
SET AUTHREC OBJTYPE(QMGR) PRINCIPAL('mquser1') AUTHADD(CONNECT,INQ)
SET AUTHREC PROFILE('QUEUE1') OBJTYPE(QUEUE) PRINCIPAL('mquser1') AUTHADD(PUT,GET,INQ,BROWSE)
其中:
INQ:查询队列的属性信息
PUT:发送给队列
GET:从队列读取消息
BROWSE:从队列读取消息,以浏览的选项设置
CONNECT:允许应用连接MQ
具体参见官网文档 [SET AUTHREC](http://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.ref.adm.doc/q086620_.htm)
文档中实例进行的的配置命令如下:
runmqlsr -t tcp -m JAVA.QUEUE.MANAGER.1 -p 1317 (通过查看进程知道,该方式和上述方式设置效果一样,但这样更简单)
runmqsc JAVA.QUEUE.MANAGER.1
DEFINE CHANNEL('JAVA.CHANNEL.1') CHLTYPE(SVRCONN) TRPTYPE(TCP) DESCR('TEST FOR JAVA')
SET CHLAUTH('JAVA.CHANNEL.1') TYPE(ADDRESSMAP) ADDRESS('192.168.98.1') MCAUSER('mquser1')
DEFINE QLOCAL('QUEUE1') DESCR('TEST FOR QUUE')
SET AUTHREC OBJTYPE(QMGR) PRINCIPAL('mquser1') AUTHADD(CONNECT,INQ)
SET AUTHREC PROFILE('QUEUE1') OBJTYPE(QUEUE) PRINCIPAL('mquser1') AUTHADD(PUT,GET,INQ,BROWSE)
end
修改后的代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
import java.io.IOException;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.MQConstants;
public class MQTest {
public static void main(String[] args) throws MQException, IOException
{
//发送消息给队列
put();
//从队列读取消息
get();
}
static void put() throws MQException, IOException
{
//配置MQ服务器连接参数
MQEnvironment.hostname = "127.0.0.1";
MQEnvironment.port = 1316;
MQEnvironment.channel = "JAVA.CLIENT.CHANNEL1";
MQEnvironment.userID = "mquser1";
MQEnvironment.password = "mqtest2016";
//设置应用名称,方便服务器MQ 查看应用连接
MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");
//创建实例,连接队列管理器
MQQueueManager queueManager = new MQQueueManager("JAVA.QUEUE.MANAGER.1");
//以可写的方式访问队列管理器已定义的队列QUEUE1,当然也可以创建队列
MQQueue putQueue = queueManager.accessQueue("QUEUE1", CMQC.MQOO_OUTPUT);
//新建并发送消息给队列
MQMessage myMessage = new MQMessage();
String name = "MePlusPlus's 博客";
myMessage.writeUTF(name);
//使用默认的消息选项
MQPutMessageOptions pmo = new MQPutMessageOptions();
//发送消息
putQueue.put(myMessage, pmo);
putQueue.close();
//断开连接
queueManager.disconnect();
}
static void get() throws MQException, IOException
{
//配置MQ服务器连接参数
MQEnvironment.hostname = "127.0.0.1";
MQEnvironment.port = 1316;
MQEnvironment.channel = "JAVA.CLIENT.CHANNEL1";
MQEnvironment.userID = "mquser1";
MQEnvironment.password = "mqtest2016";
//设置应用名称,方便服务器MQ 查看应用连接
MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");
//创建实例,连接队列管理器
MQQueueManager queueManager = new MQQueueManager("JAVA.QUEUE.MANAGER.1");
//以可读的方式访问队列管理器已定义的队列QUEUE1
MQQueue getQueue = queueManager.accessQueue("QUEUE1", CMQC.MQOO_INPUT_AS_Q_DEF);
//从队列读取消息
MQMessage theMessage = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
getQueue.get(theMessage, gmo);
String name = theMessage.readUTF();
System.out.println(name);
getQueue.close();
//断开连接
queueManager.disconnect();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
# /home/jdk1.8.0_102/bin/javac -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar MQTest.java
# /home/jdk1.8.0_102/bin/java -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:/home/mq MQTest
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-526ced5128.css" rel="stylesheet">
</div>
</article>