一、概述
消息服务是一种在分布式应用之间提供消息传递服务的软件,具有可靠、异步、宽松结合、语言中立、平台中立的特点,而且通常是可配置的。它的实现原理是:对发送者和接收者之间传递的消息进行封装,并在分布式消息客户程序结合的位置加上一个软件处理层。消息服务为消息的客户程序提供了一个接口,这个接口隔离了底层的消息服务,使得各种不同的客户程序能够通过一个友好的编程接口方便地通信。
Java消息服务(Java Message Service,JMS)是一个Java API,它定义了消息的客户程序如何以一种标准化的形式与底层的消息服务提供者交互。JMS提供了一种接口,底层消息服务提供者通过该接口向客户程序提供JMS消息服务。JMS提供了点对点消息模式(Point-to-Point)和发布-订阅消息模式(Publish-Subscribe)。点对点消息模式通过一个消息队列实现,消息的生产者向队列写入消息,消息的消费者从队列提取消息。发布-订阅消息模式通过一个话题(Topic)节点构成的层次结构实现,消息的生产者向这个层次结构发布消息,消息的消费者向这个结构订阅消息。
点对点消息模式具有如下特点:
每一个消息只有一个消费者。
消息的接收者和发送者之间不存在时间上的依赖关系。不论发送者发送消息时接收者是否在运行,接收者都可以提取信息。接收者对于成功处理的消息给出回执。
发布-订阅消息模式具有如下特点:
每一个消息可以有多个消费者。
向某个话题订阅的客户程序只能收到那些在它订阅之后发布的消息。为了接收到消息,订阅者必须保持活动状态。因此,发布者和订阅者之间存在时间上的依赖关系。
JMS API在一定程度上放宽了对这种依赖关系的要求,允许创建持久性订阅(Durable Subscription)。有了持久性订阅,当订阅者不活动时发送的消息也能接收到。
EJB 2.0规范定义了一种新的EJB类型,即消息驱动的EJB(Message-Driven EJB,简称MDB),它能够以EJB的形式实现JMS消息的接收者。消息驱动的EJB实现一组新的接口,这组接口使得EJB能够异步地接收和处理JMS消息生产者发送到队列或话题的消息。EJB客户程序的构造方式与普通JMS消息生产者的构造方式完全一样,也就是说,JMS消息生产者不必知道消息的消费者是一个EJB。
相对于会话Bean和实体Bean而言,消息驱动的Bean最大的特点是客户程序不通过接口访问Bean。与会话Bean和实体Bean不同,消息驱动的Bean只有一个Bean类。从某些方面看,消息驱动的Bean类似于无状态会话Bean:消息驱动的Bean不为特定的客户保留数据或对话状态。
一个消息驱动Bean的所有的实例都是等价的,这使得容器能够把消息指派给任意一个消息驱动Bean的实例。容器能够建立消息驱动Bean的缓冲池,实现消息的并发处理。一个消息驱动的Bean能够处理来自多个客户程序的消息。
消息驱动Bean的实例变量可以在处理客户消息期间包含一些状态信息,例如JMS连接、打开的数据库连接,或者是对EJB对象的引用。当一个消息到达,容器调用消息驱动Bean的onMessage()方法处理消息。onMessage()方法通常把消息定型(cast)成为五种JMS消息类型之一,然后按照应用的业务逻辑的要求处理消息。
传递给消息驱动Bean的消息可能处于一个事务之内,这时,onMessage()方法内的所有操作都属于该事务的一部分。如果消息处理结果被回退,则系统将再次投递该消息。
哪些时候应该使用消息驱动的Bean呢?会话Bean和实体Bean能够发送JMS消息,能够同步接收消息,但不能异步接收。一些时候,为防止过多地占用服务器资源,在服务器端的组件中,我们想要避免阻塞,这时,我们可以用消息驱动的Bean异步接收消息。