RSS
热门关键字:
当前位置 : 主页>编程开发>软件工程>列表

利用JMS建立消息传递系统

来源:我要研发网 作者: 时间:1970-01-01 点击:



  在开始之前需要说明,为了理解本文,我们希望读者拥有Java编程相当坚实基础。我们将试图尽可能简单地解释什么是JMS,但是在你能够建立自己程序并正确地理解它们之前,你需要有一些使用JNDI开发实际应用程序经验。

字串1

  JMS(Java消息服务)是一个消息交换标准,它允许使用J2EE应用程序组件建立、发送、接收和读取消息。它假设分布式通讯拥有自由(free)连接、是可靠(reliable)和异步(asynchronous)。

字串4

  Exchange(交换)系统

字串9

  消息交换反映了程序组件或应用程序之间一种交互作用。消息交换系统是一种类似于下系统:一个相似系统客户端可以发送和接收任何其它客户端消息。每个客户端都并入系统代理中,它提供了建立、发送、接收和读取消息可能。

字串9

  交换系统使得分布式交互操作成为可能。组件在目地(Destination)发送消息,收件人也可以在相同地中得到这个消息。发送者和收件人不一定是互相熟悉。换句话说,它并没有强迫发送者知道一些收件人信息,也没有强迫收件人知道某些发送者信息。发送者和收件人只需要知道消息格式以及要到达地。在这种情形下,上述系统不同于与它紧密相连一些技术,例如远程方法调用(RMI),它只要求开发人员了解RMI中一些方法。

字串9

  消息传递系统

字串2

  消息传递系统是一种分布式系统,是基于系统组件之间异步消息交换。面向消息中间件(Message-Oriented Middleware,MOM)就是这种产品,消息传递系统是在它原理上建立字串4

  消息传递系统应用软件不会直接地通讯(这与传统系统(基于RMI)形成鲜明对照),而需要依赖MOM帮助。如果系统某个组件希望给另一个组件发送消息,它将把给定消息发送给MOM,接着MOM把该消息发送给收件人。 字串5

   字串7

  与传统基于RMI构建系统相比,它有以下优点:

字串1


字串5

  · 发送消息应用程序不需要期待回应,可以继续执行。

字串9

  · 没有强迫发送消息应用程序和特定消息收件人在某个特定时刻是激活。如果消息收件人不是激活,MOM保证收件人一旦激活就立即收到该消息。

字串9

  · 系统组件没有直接地彼此相连。它们被分离开了,这就是在运行时刻能把组件从一个主机传输到另一个、却不会中断系统可用性原因。 字串2

  消息交换模型:点对点模型和发表-预订模型

字串9

  目前有两种“基本”消息交换模型:点对点模型和发表-预订(pub-sub)模型。点对点模型应用于一个或多个组件(发送者)仅仅给一个组件收件人(接收者)发送消息情形。这种模型是基于消息队列概念:发送者把消息发送到队列中,接收者从该队列中读取消息。在点对点模型中,相同队列上可能存在多个接收者,但是MOM只给其中一个传递消息。给哪一个传递消息依赖于MOM实现(implementation)。 字串7

  发表-预订模型应用于一个或多个组件(发表者)给一个或多个组件收件人(预订者)发送消息情形。这种特定模型是基于消息主题(message topic)概念:发表者把消息发送到某个主题中,而该特定主题预订者接收这些消息。 字串7

  发表-预订模型看起来更加“优雅”,但是很多发表-预订模型不能保证消息按照发送次序传递(它与点对点模型相反,点对点队列实现了FIFO(先进先出)原理)。因此,消息次序很重要(或者为了同步需要使用消息头和属性部分)时候,就应该避免采用发表-预订模型。

字串9

  Java消息服务(JMS)是使用面向消息中间件一套Java API,它允许你应用程序建立、发送、接收和读取消息。这组程序集位于J2EE程序包结构树上javax.jms程序包中。JMS在很多MOM产品中得到了实现,其中iPlanet Message Queue、 IBM MQSeries、Progress Software SonicMQ、BEA WebLogic Server、Prism Technologies OpenFusion等最有名气,也存在一些免费实现。

字串4

  JMS同时支持消息交换两种“基本”模型。但是,其说明(specification)并没有要求厂商同时实现两种模型,尽管大多数JMS产品实现了点对点和发表-预订模型。 字串2

  JMS应用程序 字串1

  JMS应用程序主要部分是:

字串3

  · 产生连接部分和目字串5

  · 连接

字串8

  · 对话

字串7

  · 产生消息部分 字串9

  · 使用消息部分 字串3

  · 消息

字串6

  产生连接部分(ConnectionFactory)是负责建立JMS连接对象。每个ConnectionFactory都是QueueConnectionFactory或TopicConnectionFactory一个副本(copy)。MOM管理器建立特定对象,并把它与JNDI树关联起来,这样JMS客户端就能够使用标准JNDI查找表得到ConnectionFactory入口。在点对点模型中,它使用了javax.jms.QueueConnectionFactory;在发表-预订模型中,它使用是javax.jms.TopicConnectionFactory。

字串5


字串5

  目地(Destination)——它是队列或主题,这依赖于我们使用了下面哪种模型:javax.jms.Queue或javax.jms.Topic。

字串3

  连接(Connection)——它可能是客户端和服务应用之间开放TCP/IP。它可以被用于建立一个或少量对话。在你应用程序能够接收消息前,你必须调用start()方法。为了暂停发送消息,你需要调用stop()。

字串5

  对话(Session)——在JMS连接帮助下建立对象,被客户端用作发送和接收消息。

字串8

  产生消息部分(MessageProducer)——对话建立对象,被用于在目地中发送消息。

字串4

  使用消息部分(MessageConsumer)——对话建立对象,用于接收消息。为了同步接收消息,需要使用receive()方法。对于异步情形,使用MessageListener和唯一方法——onMessage()。在该方法中,在定义消息到达后应该执行一定操作。 字串2

  消息(Message)——消息本身。JMS消息由三个部分组成:

字串8

  · 消息头

字串4

  · 属性(不是必要

字串1

  · 消息体(不是必要字串6

  本文没有解释更多细节信息,你可以在官方文档中找到具体细节。

字串4

  什么时候使用EJB 2.0 字串5

  请注意下述各项内容:

字串2

  在新EJB 2.0规范中,与JMS集成是通过建立新EJB类型——消息驱动Bean(MDB)来实现。MDB特性是客户端不会使用远程接口(remote interface)与它通讯。其交互操作唯一途径是通过消息发送。MDB仅仅是消息监听程序,是一个实现了javax.ejb.MessageDrivenBean和javax.jms.MessageListener接口类,没有任何其它功能。其中第一个接口只有两个方法:setMessageDrivenContext() 和ejbRemove()。第二个接口只有一个方法:onMessage()。这个规范还需要一个不带参数ejbCreate()建立方法。客户端不会直接与MDB通讯;它不会建立MDB。容器(container)自身决定什么时候和需要多少个MDB来处理来自特定目消息。MDB主要缺陷是它只能从一个目地接收到消息。 字串4

  代码示例

字串1

  我们假设你已经安装了J2SE(可以在http://java.sun.com/j2se/找到它),并且已经安装并运行了JBoss应用程序服务器(可以在http://www.jboss.org/找到它)。

字串6

  为了编译下面示例,你需要输入:

字串3

  javac -classpath .;C:jboss-3.2.3clientjbossall-client.jar SimpleSender.java 字串6

  为了运行它,你需要输入:

字串8


字串1

  java -classpath .;C:jboss-3.2.3clientjbossall-client.jar SimpleSender

字串2

  (在输入时,请用你自己JBoss目录代替C:jboss-3.2.3。同时还要记住,在你能够运行这些示例前,JBoss服务器必须处于运行状态。) 字串9

  了,现在我们开始建立示例发送程序和接收程序了:

字串6

// SimpleSender.java
import java.util.Properties;
import javax.jms.*;
import javax.naming.*;
public class SimpleSender {
 public static void main(String argv[]) {
  new SimpleSender();
 }
 public SimpleSender() {
  try {
   QueueConnectionFactory myQConnFactory;
   Queue myQueue;
   Properties properties = new Properties();
   properties.put(Context.INITIAL_CONTEXT_FACTORY,
           "org.jnp.interfaces.NamingContextFactory");
   properties.put(Context.URL_PKG_PREFIXES, "org.jnp.interfaces");
   properties.put(Context.PROVIDER_URL, "localhost");
   Context ctx = new InitialContext(properties);
   myQConnFactory = (QueueConnectionFactory)ctx.lookup
            ("UIL2ConnectionFactory");
   myQueue = (Queue) ctx.lookup("queue/testQueue");
   ctx.bind ("SimpleSender", myQueue);
   QueueConnection con = myQConnFactory.createQueueConnection();
   QueueSession session = con.createQueueSession(false, 字串5
              Session.AUTO_ACKNOWLEDGE);
   TextMessage textMessage = session.createTextMessage();
   QueueSender sender = session.createSender(myQueue);
   con.start();
   for (int i=0; i<10; i ) {
    textMessage.setText("Hello World #" i);
    sender.send(textMessage);
   }
   con.close();
   ctx.close();
  } catch(Exception e) {
   e.printStackTrace();
  }
 }
}

  我们有两种接收消息途径。第一种是使用javax.jms.QueueReceiverreceive()方法向队列同步请求消息。这可能阻塞接收程序,直到它不接收消息为止,或者如何某个消息没有在特定时间间隔内到达而返回超时操作。第二种是一旦可以访问消息了就异步接收消息,使用javax.jms.MessageListener调用onMessage()方法,它会处理消息内容。

字串3


字串6

  建立接收程序很多步骤与建立发送程序步骤类似: 字串5

// SyncReceiver.java
import java.util.Properties;
import javax.jms.*;
import javax.naming.*;
public class SyncReceiver {
 public static void main(String argv[])
 {
  new SyncReceiver();
 }
 public SyncReceiver() {
  try {
   QueueConnectionFactory myQConnFactory;
   Queue myQueue;
   Properties properties = new Properties();
   properties.put(Context.INITIAL_CONTEXT_FACTORY,
          "org.jnp.interfaces.NamingContextFactory");
   properties.put(Context.URL_PKG_PREFIXES, "org.jnp.interfaces");
   properties.put(Context.PROVIDER_URL, "localhost");
   Context ctx = new InitialContext(properties);
   myQConnFactory = (QueueConnectionFactory)ctx.lookup("UIL2ConnectionFactory");
   myQueue = (Queue) ctx.lookup("queue/testQueue");
   ctx.bind("SyncReceiver", myQueue);
   QueueConnection con = myQConnFactory.createQueueConnection();
   QueueSession session = con.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
字串3

   QueueReceiver receiver = session.createReceiver(myQueue);
   con.start();
   for (int i=0; i<10; i ) {
    TextMessage textMessage = (TextMessage) receiver.receive();
    System.out.println("Got: " textMessage.getText());
   }
   con.close();
   ctx.close();
  } catch(Exception e) {
   e.printStackTrace();
  }
 }
}

  后记 字串6

  数据库是长时间数据存储理想途径,但是用户变更临时数据和用户通知存储不是它们强项。尽管被认为是效率低下,但是数据库查询还是频繁地用于现实中。所有请求都需要大量额外“隐藏”工作,如果大量对象频繁地访问一个数据库,可能会导致数据库服务器和网络严重负载。在大多数时候,请求不会返回任何数据,更糟情形是,将已知信息返回到处理过程中。 字串7


字串5

  简单地说,数据库不是计划用于频繁查询或事件。如果一旦数据或任何事件发生了改变就要立即作出反应,那么更简单和效率更高途径将是使用异步消息。 字串6

  技术处理应用程序(例如公文流通、认领处理等)大多数使用了MQ(消息队列),因为MQ模型与技术处理模型统计特征类似,它承认“办公室”形式,在其中每个人都有自己接收和发送邮件箱。 字串8

  这类应用程序典型特征是使用了大量代理(代理可能是人、自动处理操作、甚至于物理设备,例如打印机或设备),其中每个代理都会遇到一些小性能难题,并按照业务逻辑把它传递到下一个代理。在建立这类应用程序时候,开发主要事务是对快速性能把握,同时要把握开发时失败缺乏。使用数据库MQ服务器简化了处理应用程序中技术处理过程;这样做更加灵活、容易扩展。

字串4

  同样,对于聚焦于事务应用程序,使用MQ技术也是非常方便。这涉及到处理财政金融和新服务领域一些应用程序。在财政金融市场,操作必须很快地完成;用户对于即时发生改变感兴趣。 字串1

字串9

最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
相关文章