作者:朱骐
作者简介
朱骐,男,江苏南京人,讲师,主要研究方向:信息系统与集成技术。您可以通过[email protected]和作者取得联系。
内容摘要
JMS面向Web的应用与面向桌面的应用相比,有特殊的用户环境要求:同一个消息必须能被若干未知的用户消费,因此在消息接收方必须有"接收而不确认"的提交机制;本文以CWNF校务系统为实现案例,讨论面向Web的JMS应用系统消息提交原理及采用的关键技术。
消息传递是一种在软件组件或应用之间进行分布式通信的松散耦合方法,与各种紧密耦合通信技术(如CORBA、Java RMI、COM/DCOM)相比,不同之处在于:①消息系统是一种对等实施,通信双方即消息的发送者和接受者都是该系统中的客户端,彼此不呈C/S关系; ②通信双方的工作是异步的;③基于消息格式一致,通信双方只需一个中介来存储并管理消息就可以实现通信,而紧密耦合技术则需要知道远程方法在本地的接口。 因自身特点,消息传递技术在企业中和企业间有较广泛的应用需求。
JMS(Java Message Service)是J2EE企业平台的Java消息服务,目前主流J2EE产品的JMS都实现了存储功能,JMS客户端通过JMS API创建,彼此间通过目的地(Destination)对象进行通信;可是JMS消息系统多见于桌面应用,而Web应用鲜见,本文以笔者开发的CWNF 校务系统为案例,讨论面向Web的JMS应用系统的实现原理及采用的关键技术。
1 面向Web的JMS应用系统实现原理
1.1 JMS应用系统消息传递原理
JMS应用系统有4个部分:①JMS提供者(JMS Provider),是一个逻辑数据存储体,并提供管理工具和控制特性;②JMS客户端,是用Java语言编写的发送或接收消息的组件或应用;③消息,是 JMS客户端间被传递的承载信息的对象;④被管理对象,是系统管理员为客户端预置的JMS对象,包括目的地对象和连接工厂对象,其中目的地对象是客户端间 的消息中介。这4个部分通过JNDI相关联:管理员通过管理工具把目的地对象和连接工厂对象绑定到一个JNDI API命名空间中,JMS客户端就可以在命名空间中查找这些对象,并通过JMS提供者建立与这些对象的逻辑连接,从而彼此之间实现通信(图1)。JMS支 持2种消息传递域:点到点、发布/订阅,与之相对应的消息目的地对象也有2种:队列、主题。
1.2 Web应用的消息提交机制
通常,无论是消息发送方还是接收方,桌面应用都不容许消息丢失或重复,JMS消息提交机制是基于这个要求的,它们从不同方面保证该要求的实现:①在 接收方控制消息的确认。通过确认保证一个接收者对一个消息只消费一次,在非事务性的会话中,消息确认方式取决于create×××Session方法第二 个参数的值;在事务性会话中,无论由Bean管理事务还是由Bean容器管理事务,消息确认都由Bean容器自动完成。②在发送方指定消息的提交模式和生 存期。提交模式有两种:PERSISTENT(稳定存储)和NON_PERSISTENT(非稳定存储),稳定存储保证在故障情况下消息不会丢失;生存期 决定一个消息在存储中介中的存在寿命,JMS提供者会自动摧毁到期的消息。③创建持久定阅的接收方。在发布/订阅系统中,持久订阅者可以接收到在订阅者关 闭阶段消息发送方发布的消息。
但是Web应用系统在消息接收方有Web特有的用户环境要求:①若干个用户共用一个JMS客户端组件,因此消息就应向一个消息接收者提交而不需确 认,具有容器自动确认功能的Bean是无法实现这一要求的;在一个组件内如果把会话设置成事务性的,而这个组件的容器又不具有事务管理能力,则这个组件就 能做到"接收而不确认",在Web应用系统中只有Servlet组件符合这一要求。②JMS客户端的消息接收者经常关闭,为了接收在关闭期间发送来的消 息,消息接收者必定是基于主题的持久定阅者,所以面向Web的JMS应用系统必定采用发布/订阅消息传递域。
2 CWNF校务系统模型
CWNF是一个面向Web的JMS校务系统,用于校园发布通知及征求意见等校务工作,通知分为2类:普通通知和征求意见性通知。
该系统用户分成3类,用户不同,处理模型也不同,基本情况如下:①发布用户,拥有通知发布权,向主题发布通知;②署名用户,查阅通知,也可发表对征求意见性通知的反馈意见;③匿名用户,只查阅通知。
2.1 数据与数据流模型
系统中的数据因此有2类:通知、反馈。接收方接收的数据将形成一个XML文档对象,以便发往Web浏览器显示;基于这样的要求,考察下面2个问题:①系统中各方之间的数据关系,②各方数据的形式。
主要的数据关系有3个:①通知发送方与通知接收方的数据关系,②反馈发送方与反馈接收方的数据关系,③通知接收方与反馈接收方的数据关系。(如图 2)在发送方,数据(通知或反馈)是一件一件的发送,在接收方,数据(通知或反馈)则是批接收,是对应发送方数据的集合,因此在发送方没有必要把数据直接 加工成XML文档对象形式,只要生成能构成XML文档对象的元素对象即可;而通知接收方与反馈接收方的数据关系则是:每一条征求意见性通知都有相关的一个 反馈集合。
系统的数据流模型如下:
①通知发送方:表单数据→XML元素(通知)→主题(存储)
②通知接收方:主题(存储)→XML元素(通知)→XML文档(通知)→XSL显示(含表单)
③通知接收方到反馈接收方: XSL显示(含表单)→主题(存储)
④反馈接收方:主题(存储)→XML元素(反馈)→XML文档(反馈)→XSL显示(含表单)
⑤反馈发送方:表单数据→XML元素(反馈)→主题(存储)
2.2 组件模型
系统组件模型如图3:主题CWNFTopic是消息传递中介,NoticerServlet组件向发布用户发送表单,并从表单接收数据,然后生成 XML元素对象,该元素对象和其它一些数据被作为参数调用PublisherBean组件方法,向主题发送以该元素对象为消息体的消息; ReaderServlet组件处理署名用户和匿名用户查阅通知的业务,它从表单获得用户将查阅什么方面通知的有关信息后,便使用receive方法限时 阻塞地从主题接收消息并对消息进行筛选,把筛选出的若干消息的消息体取出,然后加工成XML文档对象(根元素是通知集),最后输出。 FeedbackerPubServlet用于反馈发送方的业务处理,功能与NoticerServlet相似; FeedbackerSubServlet用于反馈接收方的业务处理,功能与ReaderServlet相似;PublisherBean组件被 NoticerServlet组件和FeedbackerPubServlet组件调用,用于发送消息,容器管理发送事务,具有很高的可靠性。
3 关键的实现技术
3.1 JDOM建立、输出XML文档
JDOM是一个开放源代码的纯Java树式API,用于分析、建立、处理和序列化XML文档。在数据流模型中,XML元素和XML文档都由JDOM API建立,在发送方,通过用户提交的表单取得名/值对若干,这些数据经过JDOM方法处理生成XML元素对象,元素对象被作为消息的消息体发往主题存 储;在接收方,持久订阅者接收到若干XML元素对象后,继续通过JDOM方法建立XML文档对象。且XML文档向Web浏览器输出也依赖于JDOM的 XMLOutputte对象方法:
PrintWriter out = response.getWriter(); // out 是ServletResponse的输出流对象
serializer.output(xmldoc,out); // 通过out把XML文档输出到页面
3.2 XSL定义XML文档显示样式
XSL是可扩展的样式单语言,通知集的XML文档和反馈集的XML文档都有相关的XSL文档决定其页面显示,如通知集XML文档的XSL样式定义如下:
< xsl:stylesheet >
< xsl:template match ="/" >
< HTML >
< BODY >
< DIV >< xsl:apply-templates select ="通知集" /></ DIV >
</ BODY >
</ HTML >
</ xsl:template >
< xsl:template match ="通知集" >
< xsl:for-each select ="通知" >
</ xsl:for-each >
</ xsl:template >
</ xsl:stylesheet >
3.3 Servlet间数据的传递
3.3.1 注册/登录
用户的一些处理工作需要注册/登录后才能进行,因此注册/登录的获准信息必须能在有关Servlet组件之间传递。ServletContext 对象可设置和读取属性,使不同Servlet之间相互通信,在系统中被用于有关组件对用户身份的验证。
3.3.2 通知与反馈的数据关联
每一条征求意见性通知都有一个相关联的反馈集合,关联可通过设置消息属性实现。JMS消息(包括通知类消息)都有系统级JMSMessageID属 性,其值是唯一的,可用于表征每一条征求意见性通知,因此对任何反馈消息也可以设置一个应用级属性(CWNF中是FeedbackSN),让它取与之相关 联的征求意见性通知的JMSMessageID属性值。这样就建立了两者间的数据关联。
因此数据流模型"③通知接收方到反馈接收方: XSL显示(含表单)→主题(存储)"的实现流程如下:用户在页面上选择一条征求意见性通知后,该通知的JMSMessageID属性值将被传递给 FeedbackerSubServlet组件,该组件将使用这个属性值去匹配从主题取出的反馈消息的FeedbackSN属性,从而筛选出相关联的反馈 消息。
那么一条征求意见性通知的JMSMessageID属性值又如何传递给FeedbackerSubServlet组件呢?通过 ServletContext对象只能传递可预知信息,CWNF的做法是:由XSL为每一条征求意见性通知设置一个独立的表单,并把该通知的 JMSMessageID属性值写在表单的TEXTAREA元素框内,这样用户在表单上选择一条征求意见性通知后,该通知的JMSMessageID属性 值就随表单一起提交给FeedbackerSubServlet组件。XSL有关代码如下:
< FORM method ="post" action ="http://localhost:6888/Feedbacker/servlet
/FeedbackerSubServlet" >
< BUTTON type ="submit" > 意见反馈 </ BUTTON >
< TEXTAREA name ="序列号" rows ="1" cols ="40" >
< xsl:value-of select ="序列号" />
</ TEXTAREA >
</ FORM >
</ xsl:if >
4 结束语
JMS应用系统与数据库系统有相似性,从数据方面看,JMS消息体的数据类型支持文本和对象,所以JMS更灵活,与XML集成应用的空间更大;但从 管理上看,JMS Provider向管理员提供的管理功能远远低于DBMS提供的管理功能,因此在面向Web的应用中,JMS宜作为中小流量、管理员参与度较低的信息系统 解决方案。
转载自:http://gceclub.sun.com.cn/yuanchuang/2004_Q4/jms.html