在你的应用程序中利用IBM WebSphere MQ消息中间件提供Java消息服务开放接口
IBM WebSphere MQ(WMQ)是一套面向消息的中间件(messageoriented middlewareMOM)通过使用消息和队列简化应用程序之间的通信WMQ支持点到点的和发布/订阅消息支持多种平台包括WindowsAIXHPUX和Sun Solaris它特别适合目前的异构计算环境
对于Java开发者而言WMQ为Java应用程序提供了两种接口
为Java提供MQ基础类 一个基于WMQ本地接口的Java接口
MQ JMS Java消息服务(Java Messaging Service JMS)接口的实现
JMS通过开启Java应用程序发送和接收消息扩展了Java的互操作性JMS应用程序可以使用点到点或发布/订阅模式进行消息交换
本文描述的是使用WMQ和JMS进行开发的过程重心集中在点到点消息通过下面几步教你如何使用Java类编写JMS接口
创建WMQ对象
创建JMS管理对象
解释JMS代码
运行一个实例类发送消息和从WMQ接收消息
WMQ安装
本文使用的是winxp上的MQ 版本 (可以从下载试用版)在windows上的安装是非常简单的一路默认就可以完成安装
如果你还没有使用过WMQ也不要担心你可以使用基于Eclipse的WebSphere MQ管理器它是一个简单的用于管理WMQ的图形工具
创建MQ对象队列管理器和队列
队列是用来存储 target=_blank>存储消息的直到应用程序处理完毕才释放队列管理器拥有并管理队列要创建一个队列管理器和队列按以下步骤启动WebSphere MQ管理器开始?所有程序? IBM WebSphere MQ ? WebSphere MQ Explorer图显示了启动WebSphere MQ管理器时的样子
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 WebSphere MQ 管理器
在MQ管理器中执行下列操作创建一个队列管理器
在导航视图下右击队列管理器选择新建队列管理器启动创建队列管理器向导
在第一步中输入队列管理器的名字TestMQ点击下一步如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 创建队列管理器第一步输入队列管理器名称
在第二步和第三步都点击下一步进入第四步确定选中了创建一个TCP/IP监听器然后输入一个未使用的端口号点击完成如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 创建队列管理器第四步检查队列管理器的监听器端口号
接下来创建两个队列INQUEUE 和 OUTQUEUE你就可以将消息写入INQUEUE从OUTQUEUE读取消息
在TestMQ下右击队列?新建?本地队列启动新建本地队列向导
在名称区域输入INQUEUE点击完成如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 创建队列向导输入队列名称其它属性值保留默认值
重复上面的步骤创建好队列OUTQUEUE
创建JMS管理对象
JMS定义了一个通用的接口来发送和接收消息只要与之通信的程序兼容JMS即可点到点的JMS接口是
javaxjmsQueueConnection 这个接口提供一个到JMS提供程序的连接用于创建会话对象
javaxjmsQueueSession 这个接口为产生和消耗消息提供上下文呢包括创建QueueSender和QueueReceiver的方法
javaxjmsQueueSender 这个接口用于向队列发送消息javaxjmsQueueReceiver用于从队列接收消息
为了让你的代码可以在不同的消息提供程序间有良好的移植性你必须在你的应用程序中使用javaxjms中的标准JMS接口所有特定厂家的信息都封装在javaxjmsQueueConnectionFactory 和 javaxjmsQueue中这些管理对象可以使用厂家提供管理工具进行构建存储在JNDI命名空间中JMS应用程序可以从命名空间中检索这些对象这时就不需要知道是哪个厂家提供的了
按照下面的步骤使用Websphere MQ管理器创建管理对象存储在基于文件的目录下
在JMS管理对象上点击右键?添加初始上下文
在屏幕上
为JNDI存储在哪里选择文件系统
在关联目录处输入C:\JNDIDirectory(前提是这个目录已经存在)
注意工厂类和提供程序URL因为你将会在Java代码中使用到(如图所示)
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 添加初始上下文向导你将在样例类中使用工厂类和提供程序URL
你的管理器现在应该如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 添加初始上下文后的MQ管理器你可以在MQ管理器中轻易地创建JMS管理对象
在新的初始上下文中创建一个连接工厂
在连接工厂上点击右键?新建?连接工厂在第一个屏幕上在名称区域输入TestQM_QCF点击下一步在JNDI查找中你就使用TestQM_QCF了
将类型设置为队列连接工厂点击下一步如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 新建连接工厂向导用于点对点消息的队列连接工厂
保持传送类型为汇集点击下一步当WMQ和应用程序在同一机器上时使用汇集传输
在下一页面点击下一步(无需修改设置)
在最后一页选择连接标签点击选择按钮选择TestQM作为基础队列管理器如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 新建连接工厂向导连接工厂被包装为TestMQ
点击完成
接下来创建目的地对应WMQ消息的JMS管理对象
在目的地上点击右键?选择新建?目的地
在第一页上在名字区域输入INInputTestQueue作为名字确保类型设置为队列了点击下一步如图所示
src=http://imgeducitycn/img_///jpg border= twffan=done>
图 新建目的地向导使用InputTestQueue查找INQUEUE
第二页保持默认设置不变点击下一步
在最后一页
在队列管理器区域点击选择按钮选择TestQM
在队列区域点击选择按钮选择INQUEUE
点击完成
重复上述步骤创建另一个目的地OutputTestQueue它对应OUTQUEUE
理解示例类
如果你编写过JMS应用程序就很容易理解JNDIUtil 和 Tester示例类(从_JMSSource&Classeszip下载Java源文件和编译好的类)你创建的JMS管理对象隐藏了所有厂家专利实现
JNDIUtil类
JNDIUtil包括使用名字通过JNDI查找检索对象的方法参考清单你可以使用这个类中的方法检索你在MQ管理器中定义的JMS对象的引用情况
清单 JNDIUtiljava
Code highlighting produced by Actipro CodeHighlighter (freeware)
>package devxarticlesmqjms;
// JMS 类
import javaxjmsJMSException;
import javaxjmsQueue;
import javaxjmsQueueConnectionFactory;
// JNDI 类
import javaxnamingInitialContext;
import javaxnamingContext;
import javaxnamingNamingException;
// 标准 Java类
import javautilHashtable;
/**
*
* A wrapper class for JNDI calls
*
*/
public class JNDIUtil
{
private Context context;
public JNDIUtil(String icf String url) throws JMSException NamingException
{
Hashtable environment = new Hashtable();
environmentput(ContextINITIAL_CONTEXT_FACTORY icf );
environmentput(ContextPROVIDER_URL url);
context= new InitialContext( environment );
}
/**
*
* @param ObjName Object Name to be retrieved
* @return Retrieved Object
* @throws NamingException
*/
private Object getObjectByName(String ObjName) throws NamingException
{
return contextlookup( ObjName );
}
/**
* A convenience method that returns QueueConnectionFactory objects (no casting required)
* @param factoryName QueueConnectionFactory JNDI name
* @return QueueConnectionFactory object
* @throws NamingException
*/
public QueueConnectionFactory getQueueConnectionFactory(String factoryName) throws NamingException
{
return (QueueConnectionFactory) getObjectByName(factoryName);
}
/**
* A convenience method that returns Queue objects (no casting required)
* @param queueName
* @return
* @throws NamingException
*/
public Queue getQueue(String queueName) throws NamingException
{
return (Queue) getObjectByName(queueName);
}
}
Tester类
Tester类向OUTQUEUE中写入消息从INQUEUE中读取消息参考清单
清单 Testerjava
Code highlighting produced by Actipro CodeHighlighter (freeware)
>package devxarticlesmqjms;
//JMS 类
import javaxjmsQueue;
import javaxjmsQueueSession;
import javaxjmsQueueConnection;
import javaxjmsQueueConnectionFactory;
import javaxjmsJMSException;
import javaxjmsSession;
import javaxjmsQueueSender;
import javaxjmsQueueReceiver;
import javaxjmsTextMessage;
import javaxjmsMessage;
//JNDI 类
import javaxnamingNamingException;
//标准 Java 类
/**
*
* A class to test JMS with IBM MQ
*
*/
public class Tester
{
public static String icf = comsunjndifscontextRefFSContextFactory;
public static String url = file:/C:/JNDIDirectory;
public static void main(String[] vars) throws JMSException NamingException
{
QueueSession session = null;
QueueConnection connection = null;
QueueConnectionFactory factory = null;
QueueSender queueSender = null;
QueueReceiver queueReceiver= null;
Queue oQueue = null; // 消息发送到的队列
Queue iQueue = null; // 接收消息的队列
try
{
JNDIUtil jndiUtil= new JNDIUtil(icfurl);
factory= jndiUtilgetQueueConnectionFactory(TestQM_QCF);
connection = factorycreateQueueConnection();
// 启动(或重新启动)入站消息的连接地址如果没有这个调用消息不会被接收
connectionstart();
//表示一个非相互操作会话
boolean transacted = false;
session = connectioncreateQueueSession( transacted SessionAUTO_ACKNOWLEDGE);
oQueue= jndiUtilgetQueue(OutputTestQueue);
queueSender = sessioncreateSender(oQueue);
TextMessage oMsg = sessioncreateTextMessage();
oMsgsetText();
// 你还可以设置其他消息属性
queueSendersend(oMsg);
iQueue= jndiUtilgetQueue(InputTestQueue);
queueReceiver = sessioncreateReceiver(iQueue);
Message iMsg = queueReceiverreceive();
if ( iMsg != null )
Systemoutprintln( ((TextMessage)iMsg)getText() );
else
Systemoutprintln( No messages in queue );
}
finally
{
//总是释放资源
if ( queueReceiver!= null )
queueReceiverclose();
if ( queueSender!= null )
queueSenderclose();
if ( session!= null )
sessionclose();
if ( connection!= null )
{
connectionclose();
}
}
}
}
开始点是连接工厂查找这个工厂用于创建一个连接
Code highlighting produced by Actipro CodeHighlighter (freeware)
>factory= jndiUtilgetQueueConnectionFactory(TestQM_QCF);
connection = factorycreateQueueConnection();
连接对象用于创建一个会话
Code highlighting produced by Actipro CodeHighlighter (freeware)
>session = connectioncreateQueueSession( transacted SessionAUTO_ACKNOWLEDGE);
要将消息写入INQUEUE queue查找前面创建的目的地对象OutputTestQueue
Code highlighting produced by Actipro CodeHighlighter (freeware)
>oQueue= jndiUtilgetQueue(OutputTestQueue);
最后创建一个QueueSender对象将消息写入队列
Code highlighting produced by Actipro CodeHighlighter (freeware)
>queueSender = sessioncreateSender(oQueue);
TextMessage oMsg = sessioncreateTextMessage();
oMsgsetText();
queueSendersend(oMsg);
从OUTQUEUE读取消息的过程相同但使用的是QueueReceiver
编译运行示例类
当你安装WMQ时会自动将编译和运行示例类需要的jar文件添加到CLASSPATH环境变量中需要的jar文件位于C:\Program Files\IBM\WebSphere MQ\Java\lib包括JMS和JNDI需要的jar
在运行Tester类之前使用MQ管理器向INQUEUE增加一条测试消息
在 INQUEUE上点击右键选择放入测试消息
输入任意文本点击放入消息
如果你还没有在INQUEUE队列中放入过消息Tester类会显示队列中无消息
要运行Tester类将Testerclass 和 JNDIUtilclass添加到CLASSPATH然后在命令提示符输入
Code highlighting produced by Actipro CodeHighlighter (freeware)
>java devxarticlesmqjmsTester
应用程序向OUTQUEUE写入一条消息并显示从INQUEUE检索到的消息要检查发送到OUTQUEUE中的消息进入MQ管理器在OUTQUEUE上点击右键?选择浏览消息即可
企业中的Java和WMQ MOM
在大型企业环境下可以充分利用WMQ的性能和稳定性优势只要你的代码遵循Java标准接口你就可以受益