WebSphere MQ Java 应用开发简单实例(下篇)(client mode和binding mode)

来源:互联网 发布:手机号被绑定淘宝账号 编辑:程序博客网 时间:2024/05/21 11:19

* MQ服务器的配置参加上篇*

4-绑定模式连接

Java应用程序必须和MQ服务器安装在同一个机器上,通过进程间通信机制,不通过TCP/IP进行通信,减少网络开销。MQ提供32和64位版本的MQ JNI库,默认在/opt/mqm/java/lib/和/opt/mqm/java/lib64/目录下:mqjbnd.so: 该库为应用提供绑定模式连接MQ;修改代码:其实变动更小,只要将主机地址和端口去掉即可,因为绑定模式不需要网络通信,此外也不需要TCP通道参数。
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 MQTest2 {    public static void main(String[] args) throws MQException, IOException     {        //发送消息给队列        put();        //从队列读取消息        get();    }    static void put() throws MQException, IOException    {        //配置MQ服务器连接参数        //用户名和密码        MQEnvironment.userID = "mquser1";        MQEnvironment.password = "mqtest2016";        //设置应用名称,方便服务器MQ 查看应用连接        MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");        //设置绑定模式通信        MQEnvironment.properties.put(CMQC.TRANSPORT_PROPERTY,CMQC.TRANSPORT_MQSERIES_BINDINGS);        //创建实例,连接队列管理器        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 博客2";        myMessage.writeUTF(name);        //使用默认的消息选项        MQPutMessageOptions pmo = new MQPutMessageOptions();        //发送消息        putQueue.put(myMessage, pmo);        putQueue.close();        //断开连接        queueManager.disconnect();    }    static void get() throws MQException, IOException    {        //配置MQ服务器连接参数        MQEnvironment.userID = "mquser1";        MQEnvironment.password = "mqtest2016";        //设置应用名称,方便服务器MQ 查看应用连接        MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");        MQEnvironment.properties.put(CMQC.TRANSPORT_PROPERTY, CMQC.TRANSPORT_MQSERIES_BINDINGS);        //创建实例,连接队列管理器        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();    }}
编译运行:# cd /home/mq# /home/jdk1.8.0_102/bin/javac -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar  MQTest2.java# /home/jdk1.8.0_102/bin/java   -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:/home/mq  MQTest2出现以下错误:
Exception in thread "main" com.ibm.mq.MQException: MQJE001: 完成代码为 '2',原因为 '2495'。    at com.ibm.mq.MQSESSION.<init>(MQSESSION.java:2065)    at com.ibm.mq.MQSESSION.getSession(MQSESSION.java:2105)    at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:210)    at com.ibm.mq.MQBindingsManagedConnectionFactoryJ11._createManagedConnection(MQBindingsManagedConnectionFactoryJ11.java:187)    at com.ibm.mq.MQBindingsManagedConnectionFactoryJ11.createManagedConnection(MQBindingsManagedConnectionFactoryJ11.java:233)    at com.ibm.mq.StoredManagedConnection.<init>(StoredManagedConnection.java:96)    at com.ibm.mq.MQSimpleConnectionManager.allocateConnection(MQSimpleConnectionManager.java:194)    at com.ibm.mq.MQQueueManagerFactory.obtainBaseMQQueueManager(MQQueueManagerFactory.java:767)    at com.ibm.mq.MQQueueManagerFactory.procure(MQQueueManagerFactory.java:715)    at com.ibm.mq.MQQueueManagerFactory.constructQueueManager(MQQueueManagerFactory.java:678)    at com.ibm.mq.MQQueueManagerFactory.createQueueManager(MQQueueManagerFactory.java:148)    at com.ibm.mq.MQQueueManager.<init>(MQQueueManager.java:675)    at MQTest2.put(MQTest2.java:38)    at MQTest2.main(MQTest2.java:18)Caused by: com.ibm.mq.jmqi.local.LocalMQ$3: CC=2;RC=2495;AMQ8598: 未能装入 WebSphere MQ 本机 JNI 库“'mqjbnd'”。    at com.ibm.mq.jmqi.local.LocalMQ.loadLib(LocalMQ.java:1236)    at com.ibm.mq.jmqi.local.LocalMQ$1.run(LocalMQ.java:280)    at java.security.AccessController.doPrivileged(Native Method)    at com.ibm.mq.jmqi.local.LocalMQ.initialise_inner(LocalMQ.java:268)    at com.ibm.mq.jmqi.local.LocalMQ.initialise(LocalMQ.java:231)    at com.ibm.mq.jmqi.local.LocalMQ.<init>(LocalMQ.java:1318)    at com.ibm.mq.jmqi.local.LocalServer.<init>(LocalServer.java:229)    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)    at com.ibm.mq.jmqi.JmqiEnvironment.getInstance(JmqiEnvironment.java:672)    at com.ibm.mq.jmqi.JmqiEnvironment.getMQI(JmqiEnvironment.java:606)    at com.ibm.mq.MQSESSION.<init>(MQSESSION.java:2058)    ... 13 moreCaused by: java.lang.UnsatisfiedLinkError: no mqjbnd in java.library.path    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)    at java.lang.Runtime.loadLibrary0(Runtime.java:870)    at java.lang.System.loadLibrary(System.java:1122)    at com.ibm.mq.jmqi.local.LocalMQ.loadLib(LocalMQ.java:1208)    ... 26 more
很明显,上述错误,是因为找不到MQ JNI库,libmqjbnd.so,重新运行,指明该库位置(注意本机是64位操作系统)# /home/jdk1.8.0_102/bin/java  -Djava.library.path=/opt/mqm/java/lib64  -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:/home/mq  MQTest2再次出错
Exception in thread "main" com.ibm.mq.MQException: MQJE001: 完成代码为 '2',原因为 '2035'。    at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:251)    at com.ibm.mq.MQBindingsManagedConnectionFactoryJ11._createManagedConnection(MQBindingsManagedConnectionFactoryJ11.java:187)    at com.ibm.mq.MQBindingsManagedConnectionFactoryJ11.createManagedConnection(MQBindingsManagedConnectionFactoryJ11.java:233)    at com.ibm.mq.StoredManagedConnection.<init>(StoredManagedConnection.java:96)    at com.ibm.mq.MQSimpleConnectionManager.allocateConnection(MQSimpleConnectionManager.java:194)    at com.ibm.mq.MQQueueManagerFactory.obtainBaseMQQueueManager(MQQueueManagerFactory.java:767)    at com.ibm.mq.MQQueueManagerFactory.procure(MQQueueManagerFactory.java:715)    at com.ibm.mq.MQQueueManagerFactory.constructQueueManager(MQQueueManagerFactory.java:678)    at com.ibm.mq.MQQueueManagerFactory.createQueueManager(MQQueueManagerFactory.java:148)    at com.ibm.mq.MQQueueManager.<init>(MQQueueManager.java:675)    at MQTest2.put(MQTest2.java:38)    at MQTest2.main(MQTest2.java:18)···    很明显,表明MQ访问的权限错误,说明在绑定模式下,MQ未能充分授权,可能是队列管理器、通道或者队列对象。    经过搜索和阅读文档,发现如下几种方式,尝试了以下方法,最终通过最后一种方法解决:    第一种尝试(**该方法不起效果**):仔细检查服务器端队列管理器和通道等配置发现,> DEFINE CHANNEL(JAVA.CLIENT.CHANNEL1) CHLTYPE(SVRCONN) TRPTYPE(TCP)> SET CHLAUTH(JAVA.CLIENT.CHANNEL1) TYPE(ADDRESSMAP) ADDRESS('127.0.0.1') MCAUSER('mquser1')    这里的channel配置是针对IP地址进行过滤和限制访问的,建立的TCP通道,因此需要新增另一种类型的通道。    需要新建一个通道,非TCP通道,命名为JAVA.CLIENT.CHANNEL2    此外发现错误:少配置了 channel的参数,加入代码:    MQEnvironment.channel = "JAVA.CLIENT.CHANNEL2";    # su - mqm    ~ cd /opt/mqm/bin    ~ source setmqenv -s    启动脚本执行器,进行设置    ~ runmqsc JAVA.QUEUE.MANAGER.1        DEFINE CHANNEL(JAVA.CLIENT.CHANNEL2) CHLTYPE(SVRCONN)         SET CHLAUTH('JAVA.CLINET.CHANNEL2') TYPE(USERMAP) ACTION(ADD) CLNTUSER('mquser1') USERSRC(MAP) MCAUSER('mquser1')    **仍然出错,其实通过绑定模式,不需要通道参数,因为它不通过网络进行通信,是利用进程间通信机制进行消息传递,上述方法无法解决**    第二种方法:(**该方法有效**)    在寻找文档和查找MQ Java API文档以后,发现了以下说明,进而找到解决方法,主要是因为执行MQTest2时,    需要切换到特定用户,本文定义队列管理器和队列时授权给mquser1。    此外,在类 com.ibm.mq.MQEnvironment的    [文档](https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.javadoc.doc/WMQJavaClasses/com/ibm/mq/MQEnvironment.html)    中有该表述:> All the methods and attributes of this class apply to the WebSphere MQ classes for Java client connections,> but only enableTracing(), disableTracing(), properties, version_notice, userID, connOptions and connTag apply to bindings connections.    翻译出来,很简单,对于绑定模式,MQEnvironment类中只有 enableTracing(), disableTracing(), properties,    version_notice, userID, connOptions and connTag 这几个方法和属性有效,所以不用设置通道,主机名等属性,    此外,properties里面很多key也就是重写了类中方法和属性而已。    因此需要修改MQTest2.java文件,删除不必要的属性,修改后的代码如下:```javaimport 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 MQTest2 {    public static void main(String[] args) throws MQException, IOException     {        //发送消息给队列        put();        //从队列读取消息        get();    }    static void put() throws MQException, IOException    {        //设置应用名称,方便服务器MQ 查看应用连接        MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");        //设置绑定模式通信        MQEnvironment.properties.put(CMQC.TRANSPORT_PROPERTY,CMQC.TRANSPORT_MQSERIES_BINDINGS);        //创建实例,连接队列管理器        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 博客2";        myMessage.writeUTF(name);        //使用默认的消息选项        MQPutMessageOptions pmo = new MQPutMessageOptions();        //发送消息        putQueue.put(myMessage, pmo);        putQueue.close();        //断开连接        queueManager.disconnect();    }    static void get() throws MQException, IOException    {        //设置应用名称,方便服务器MQ 查看应用连接        MQEnvironment.properties.put(MQConstants.APPNAME_PROPERTY, "MQ Test By Java");        MQEnvironment.properties.put(CMQC.TRANSPORT_PROPERTY, CMQC.TRANSPORT_MQSERIES_BINDINGS);        //创建实例,连接队列管理器        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();    }}
编译运行:# cd /home/mq# /home/jdk1.8.0_102/bin/javac  -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:/home/mq  MQTest2.java切换到mquser1执行:(**这个是关键**)# su - mquser1~ /home/jdk1.8.0_102/bin/java  -Djava.library.path=/opt/mqm/java/lib64  -cp /opt/mqm/java/lib/com.ibm.mq.allclient.jar:/home/mq  MQTest2

5-MQEnvironment类中的userID和password属性作用初探

MQEnvironment类中的userID和password属性:用来认证MQ应用的用户身份。如果设置了securityExit属性,应用特定的安全验证流程,则userID和password属性将不起作用被忽略;默认情况下,如果userID为空时,将默认发送JRE 属性(user.name)作为该属性值;如果设置了,则发送设置值;此外,目前SecurityExit该接口已经过期,对于绑定模式(binding mode),SecurityExit接口不支持。因此,userID和password表明应用身份,要和MQ服务器端的安全设置配合使用,本文的示例程序中并没有用上该属性。上述MQ设置:SET AUTHREC PROFILE(QUEUE1) OBJTYPE(QUEUE) PRINCIPAL('mquser1') AUTHADD(PUT,GET)principal属性表明 用户mquser1对于该队列管理器中的队列具有put,get权限。SET AUTHREC OBJTYPE(QMGR) PRINCIPAL('mquser1') AUTHADD(CONNECT)principal属性表明mquser1对于队列管理器具有连接的权限DEFINE CHANNEL(JAVA.CLIENT.CHANNEL1) CHLTYPE(SVRCONN) TRPTYPE(TCP)SET CHLAUTH(JAVA.CLIENT.CHANNEL1) TYPE(ADDRESSMAP) ADDRESS('127.0.0.1') MCAUSER('mquser1')这条很重要,表明通过IP地址进行连接过滤,表明127.0.0.1这台机器可以通过通道JAVA.CLIENT.CHANNEL1,并以mquser1的身份访问队列管理器。也就是说127.0.0.1这台机器无需传递任何身份信息。那么该userID和password作用有哪些?实验:对于上述实例中的TCP方式访问的代码,1.不设置该属性,正常运行;2.设置为mquser1和正确的password,正常运行;3.设置mquser1和不设置password属性,正常运行4.设置为mquser1和错误的密码无法访问 5.设置不存在的用户mquser2,也无法访问; 6.添加用户mquser2,正常运行说明MQ服务器对于应用传递过来的userID和password属性并没有忽略,而是一种方式在验证,从上看出是以验证操作系统用户的方式在验证。此外配合MQ的权限设置,可以SET CHLAUTH(' generic-channel-name ') TYPE (USERMAP) CLNTUSER(client-user-name) USERSRC(MAP) MCAUSER(user)通过用户映射,将应用传递过来的userID(也就是client-user-name) 映射成 系统的user(MCAUSER属性)MQ 安全机制是很复杂的主题,本文未继续深究,对于该属性的安全验证机制,如有新见解,欢迎留言和赐教~~
0 0