近日开发一个Message Driven Bean实现的异步计算功能,整理之后希望可以和各位正在做MDB或者JMS开发的朋友分享一下。
这是一个MIS系统的一部分,用于计算最后的收费金额,由于计算过程及其复杂,要求实现不影响用户接口响应,就是要实现异步计算,同时可以处理多个计算请求,计算结束后通知发出计算命令的客户端。功能十分简单,只要一个MDB就可以实现了,但是要通知客户端计算结束使得系统变得有趣多了。
JMS API
在进行系统设计之前我们先回头熟悉一下JMS的一些概念。JMS源于企业应用对于消息中间件的需求,使应用程序可以通过消息进行异步处理而互不影响。JMS应用程序有四个组成部分:JMS服务提供者、消息管理对象、消息的生产者消费者和消息本身。
l JMS服务提供者实现消息队列和通知,同时实现消息管理的API。JMS已经是J2EE API的一部分,J2EE服务器都提供JMS服务。
l 消息管理对象提供对消息进行操作的API。JMS API中有两个消息管理对象:ConnectionFactory和Destination,根据消息的消费方式的不同ConnectionFactory可以分为QueueConnectionFactory和TopicConnectionFactory,Destination可以分为Queue和Topic。用这两个管理对象可以建立到消息服务的会话。
l 消息的生产者和消费者。它们可以毫不相干,只需要消息的消费者知道如何使用消息即可。根据消息消费者数目的不同,消息的消费者分为两类:subscriber 和receiver,同样消息发送者也分为两类:Publisher和Sender。
l 消息。JMS API规定了五种消息:Message、MapMessage、TextMessage、ByteMessage、StreamMessage和ObjectMessage
消费形式的不同造成JMS有两组平行的API,这就是JMS的PTP(point to point)模型和PUB/SUB(publisher和subscriber、出版和订阅)模型。PTP的消息应用中一个消息只有一个消费者,消费后该消息即不再有效。而PUB/SUB应用中一个消息可以有多个订阅者,而且每个订阅者不一定非要处理该消息。
下面是JMS应用的基本模型:
(该图引自sun的在线文档 JMS Tutorial)
根据该模型列出JMS中几个最长用的API:
l QueueConnectionFactory和TopicConnectionFactory 连接工厂用来生成QueueConnection和TopicConnection的实例
l QueueConnection和TopicConnection连接对象用来建立到JMS的连接并生成会话实例
l QueueSession和TopicSession会话对象用来创建消息、消息的生产者和消息的消费者(解释一下消息的生产者:它并不代表生成消息实例的对象而是指将消息发送到JMS的对象)
l QueueSender、TopicPublisher和QueueReciever、TopicSubscriber。消息的生产者和消费者,QueueSender的send方法和TopicPublisher的publish方法发送消息到Destination。QueueReciever和TopicSubscriber直接使用父接口MessageConsumer中定义的方法receive、recieveNoWait等方法来接收消息,setMessageListener方法来设置消息监听器。QueueReciever的getQueue方法得到Queue的引用,TopicSubscriber的getTopic方法得到Topic的引用。
l MessageListener,消息监听器。改接口只有一个方法onMessage(),改方法只有一个Message类型的参数,通过MessageConsumer(QueueReciever和TopicSubscriber共同的父接口)的setMessageListener方法注册后,系统在收到消息后调用改方法。
l Queue和Topic,消息Destination。主要的作用就是存储消息。
设计
系统过于简单就不设计了,这里简单交代一下软件的运行环境和执行流程,这个MIS系统是B/S模式的,Web Browser在完成添加执行任务(保存到数据库)的工作后要发一个消息给计算程序,这个计算过程就实现成MDB,计算结束后将完成的消息发给生成任务的Web Browser,各位不要以为我真的能这样做,主动式的把消息发送给Web Browser笔者还没有这份功力,这里采用了一个取巧的方法:在Web页中使用一个Applet,该Applet本身也是一个一直运行的线程,并且每隔一段时间访问接收消息的Servlet,如果有收到消息则提示用户。这个Servlet就是一个MessageConsumer了,而MDB就是MessageProducer了。而在产生执行任务的时候,保存执行任务的jsp/servlet则是MessageProducer,而运行MDB的EJB Container则成了MessageCunsumer,MDB则成为一个消息监听器。由于有两种消息笔者偷懒就使用了两个Destination(跟上面图不谋而合,哈哈),一个用来存放执任务的消息,一个用于存放任务完成的消息。具体实现当然有消息内容的设计和实现,不过对于系统结构并不影响,这里就不废话了。
开发工具是JBuilder和WebLogic。
动手实现
1. 发送和接收消息。需要使用JMS API手动编码实现发送和接收消息的有三个地方:发送消息的Servlet、接收消息的Servlet和发送计算完成消息的MessageDrivenBean。对于发送和接收消息都需要的QueueConnectionFactory、QueueConnection、Queue和QueueSession等对象则利用Servlet和MDB的生命周期方法获得和释放,在Servlet的init方法和MDB的ejbCreate方法中获得资源并创建需要的对象,在Servlet的destroy和MDB的ejbRemove方法中释放资源。
获得资源:
public void init() throws ServletException {
try{
InputStream in = this.getClass().getClass().getClassLoader().
getResourceAsStream("jndi.properties");
Properties p = new Properties();
p.load(in);
ctx = new InitialContext(p);
}catch(Exception ex){
ex.printStackTrace();
}
try{
connectionFactory = (QueueConnectionFactory) ctx.lookup(
connectionFactoryName);
queue = (Queue) ctx.lookup(queueName);
connection = (javax.jms.QueueConnection) ( (QueueConnectionFactory)
connectionFactory).
createQueueConnection();
queueSession = ( (javax.jms.QueueConnection) connection).
createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queue);
}catch(Exception ex){
ex.printStackTrace();
}
}
发送消息:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String taskid = request.getParameter("taskid");
try{
String completedmsg = "任务" + taskid + "执行完成";
ObjectMessage om = queueSession.createObjectMessage(new CalculateCompleted(userid, taskid, completedmsg));
queueSender.send(om);
}catch(Exception ex){
ex.printStackTrace();
}
}
接收消息。这里对消息在Servlet中作了转存,messages是一个Hashtable对象。
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
boolean rflag = true;
try {
messageConsumer = (QueueReceiver) queueSession.createReceiver(queue);
connection.start();
while (rflag) {
Message m = messageConsumer.receiveNoWait();
if (m != null) {
if (m instanceof ObjectMessage) {
ObjectMessage message = (ObjectMessage) m;
MessageBody mb = (MessageBody)message.getObject();
ArrayList a = (ArrayList)messages.get(mb.getUserID());
if(a == null){
a = new ArrayList();
a.add(mb);
messages.put(mb.getUserID(), a);
}else{
a.add(mb);
}
}
else {
rflag = false;
}
}
else {
rflag = false;
}
}
connection.stop();
}
catch (JMSException e) {
e.printStackTrace();
}
}
释放资源:
public void destroy() {
try{
if(connection != null)connection.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
MDB的jebCreate方法和上面init方法的内容一样,ejbRemove和上面destroy方法的内容相同。MDB的计算过程实现在onMessage()方法中,计算完成后发送一条消息,发送消息的过程上面已有,不再赘述。
2. WebLogic的JMS服务配置。这里使用最简单的JMS配置,除了名字和JNDI名其余的均使用缺省值。
a) 启动WebLogic,打开web console
b) 展开左侧的JMS节点,新建一个JMS Server。名字随意。
c) 为刚建立的JMS Server建立两个Queue。JNDI名分别为::jms/calculate和jms/completed。
d) 建立一个ConnectionFacotry。JNDI名:jms/conn_factory
3. 配置MDB。这里除了要指定MDB监听的Queue外,因为MDB需要向另外的Queue发送计算成功的消息,还需要把上面WebLogic中配置的jms/conn_factory作为资源添加到MDB的resource-ref中,把jms/completed作为环境资源添加到MDB的resource-env-resource中。
4. 部署执行。用JBuilder建立一个EAR然后部署,非常简单。如果各位想要测试只需要建立一个简单的客户端应用程序,然后将MDB的onMessage方法简单实现为消息转发就可以了。
总结
笔者初学JMS,只能说说JMS最基本的应用。JMS是一组很强大的API,不仅可以在一个应用程序中实现异步通信,也常被用来在不同的应用程序间传递数据,同时JMS也支持分布式事务,达到了企业应用的要求,笔者相信随着学习和应用的不断深入,将会发现JMS更强大的功能。
分享到:
相关推荐
Spark 入门实战系列,适合初学者,文档包括十部分内容,质量很好,为了感谢文档作者,也为了帮助更多的人入门,传播作者的心血,特此友情转贴: 1.Spark及其生态圈简介.pdf 2.Spark编译与部署(上)--基础环境搭建....
本篇主要聚焦于HP服务器上的RAID配置,特别是RAID5的实战配置,这是一种平衡性能、容量和冗余的解决方案。 RAID5是RAID级别中的一种,它提供了数据的分布式奇偶校验,允许在阵列中丢失任意一块硬盘的情况下仍能保持...
由于现在流行的转贴工具都是基于浏览器的,转换速度比较慢,还得打开浏览器才能使用(同时受到浏览器版本限制)。 <br> 而这个小程序则完全不依赖于浏览器,以BFC采集器的UBB转换模块为基础,转换速度超快,...
"动网转贴"这个主题可能指的是在论坛或者社交网络中实现帖子转发或分享的功能。 动网转贴的源码可能涉及到以下几个方面的知识点: 1. **网络通信**:在实现动网转贴功能时,首先需要与服务器进行交互,发送用户的...
【标题】"动网转贴.e.rar"是一个压缩文件,很可能包含了有关动网论坛或社区的相关资源、数据或用户帖子的备份。动网是中国早期知名的网络论坛软件之一,提供了丰富的社区功能,允许用户发帖、回帖、互动等。这个...
《动易系统的论坛转贴工具详解与应用》 在互联网信息交流日益频繁的今天,论坛作为用户互动的重要平台,其内容分享与传播的作用不容忽视。动易系统的论坛转贴工具,便是为了解决用户在论坛间便捷分享内容而设计的一...
"动网转贴"可能是基于易语言编写的一个功能模块或者工具,用于在论坛或者网站之间转移帖子数据。由于压缩包文件名为“易语言动网转贴.rar”,我们可以推测这可能是一个软件开发资源,包含了一些源代码、教程或者是...
去除Html中的干扰码等(样例中以轻之国度的干扰码为例) 配置文件语法: 方法类型(整数) 最大匹配长度(整数) 字符串1(删除开头) 字符串2(删除结尾) 方法类型: 1:删除单行 2:删除行与行之间的
在“导电泡棉转贴装置”这个特定的场景下,我们可能是在讨论一种用于电子政务设备或系统中的特殊组件。 导电泡棉是一种具有导电性能的泡沫材料,通常用于电子设备的屏蔽、接地或防静电保护。在电子政务设备中,这种...
东度极品论坛转贴工具东度极品论坛转贴工具
在本主题中,我们将深入探讨如何利用jQuery实现“转贴”功能,这是一种常见的社交媒体分享功能,允许用户将网页内容轻松分享到各种社交网络。 首先,让我们了解一下jQuery的核心概念。jQuery通过一种简洁的语法提供...
《易语言项目实例——动网转贴》 易语言,作为一种中文编程语言,以其独特的语法和易用性,深受广大编程爱好者尤其是初学者的喜爱。这个名为“动网转贴”的项目,是易语言编程实践中一个典型的例子,它为学习者提供...
本压缩包文件"行业分类-设备装置-FPC吸附胶纸转贴组件.zip"主要关注的是FPC在实际应用中的一个重要环节——FPC吸附胶纸转贴组件。这个组件在FPC的制造和组装过程中起到关键作用,确保FPC能够稳定地固定在设备上,并...
转贴一个网络设计的例子
标题中的“论坛专用屏蔽干扰码转贴工具”指的是一个专为论坛设计的软件,它的主要功能是处理并转换论坛上常见的干扰码,以便用户能够顺利地复制和粘贴信息。在论坛交流中,有时为了防止恶意爬虫或者保护内容不被搜索...
本篇将详细探讨“电子功用-导电胶配对模切对半转贴加工方法”,这是一种高效的生产工艺,旨在提高电子产品的性能和可靠性。 导电胶主要由导电填料(如金属颗粒)、树脂基体和添加剂组成。它的特性在于既能保持良好...
"易语言动网转贴"是指使用易语言编写的一段代码或程序,主要用于在动网上实现帖子的转换或者迁移。动网可能是一个论坛或社区平台,转贴功能则是将某个地方的帖子复制到另一个地方,保持其内容完整。 在这个源码中,...
论坛转贴工具提供常的转换追加,转换覆盖,预览贴子,分析超链接,屏蔽文字,图片,超链接,提供查找,替换等功能,HTML版! 支持IE浏览器,360浏览器,搜狗浏览器,火狐浏览器,谷歌chrome浏览器等主流浏览器,无需...
《木器、玻璃用贴花纸生产及转贴方法》是一个深入探讨装饰材料工艺的行业文档,主要聚焦于贴花纸在木器和玻璃制品上的应用。这份文档可能包含了从贴花纸的设计、生产到实际转贴过程中的各种技术细节和实践经验。 1....