在开始之前需要说明,为了理解本文,我们希望读者拥有Java编程
相当坚实
基础。我们将试图尽可能简单地解释什么是JMS,但是在你能够建立自己
程序并正确地理解它们之前,你需要有一些使用JNDI开发实际应用程序
经验。
JMS(Java消息服务)是一个消息交换标准,它允许使用J2EE应用程序组件建立、发送、接收和读取消息。它假设分布式通讯拥有自由(free)
连接、是可靠
(reliable)和异步
(asynchronous)。
字串4
Exchange(交换)系统
消息交换反映了程序组件或应用程序之间
一种交互作用。消息交换系统是一种类似于下
系统:一个相似系统
客户端可以发送和接收任何其它客户端
消息。每个客户端都并入系统
代理中,它提供了建立、发送、接收和读取消息
可能。
交换系统使得分布式
交互操作成为可能。组件在目
地(Destination)发送消息,收件人也可以在相同
目
地中得到这个消息。发送者和收件人不一定是互相熟悉
。换句话说,它并没有强迫发送者知道一些收件人
信息,也没有强迫收件人知道某些发送者
信息。发送者和收件人只需要知道消息
格式以及要到达
目
地。在这种情形下,上述
系统不同于与它紧密相连
一些技术,例如远程方法调用(RMI),它只要求开发人员了解RMI中
一些方法。
消息传递系统
消息传递系统是一种分布式
系统,是基于系统组件之间
异步消息交换。面向消息
中间件(Message-Oriented Middleware,MOM)就是这种产品,消息传递系统是在它
原理上建立
。 字串4
消息传递系统应用软件不会直接地通讯(这与传统
系统(基于RMI
)形成鲜明
对照),而需要依赖MOM
帮助。如果系统
某个组件希望给另一个组件发送消息,它将把给定
消息发送给MOM,接着MOM把该消息发送给收件人。 字串5
字串7
与传统
基于RMI构建
系统相比,它有以下优点:
字串5
· 发送消息
应用程序不需要期待回应,可以继续执行。
字串9
· 没有强迫发送消息
应用程序和特定消息
收件人在某个特定
时刻是激活
。如果消息
收件人不是激活
,MOM保证收件人一旦激活就立即收到该消息。
· 系统组件没有直接地彼此相连。它们被分离开了,这就是在运行时刻能把组件从一个主机传输到另一个、却不会中断系统可用性
原因。 字串2
消息交换模型:点对点模型和发表-预订模型
目前有两种“基本
”消息交换模型:点对点模型和发表-预订(pub-sub)模型。点对点模型应用于一个或多个组件(发送者)仅仅给一个组件收件人(接收者)发送消息
情形。这种模型是基于消息队列概念
:发送者把消息发送到队列中,接收者从该队列中读取消息。在点对点模型中,相同
队列上可能存在多个接收者,但是MOM只给其中一个传递消息。给哪一个传递消息依赖于MOM
实现(implementation)。 字串7
发表-预订模型应用于一个或多个组件(发表者)给一个或多个组件收件人(预订者)发送消息
情形。这种特定
模型是基于消息主题(message topic)概念
:发表者把消息发送到某个主题中,而该特定主题
预订者接收这些消息。 字串7
发表-预订模型看起来更加“优雅”,但是很多发表-预订模型不能保证消息按照发送
次序传递(它与点对点模型相反,点对点队列实现了FIFO(先进先出)原理)。因此,消息
次序很重要(或者为了同步需要使用消息
头和属性部分)
时候,就应该避免采用发表-预订模型。
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
本文没有解释更多
细节信息,你可以在官方文档中找到具体
细节。
什么时候使用EJB 2.0 字串5
请注意下述各项内容:
在新
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
代码示例
我们假设你已经安装了J2SE(可以在http://java.sun.com/j2se/找到它),并且已经安装并运行了JBoss应用程序服务器(可以在http://www.jboss.org/找到它)。
为了编译下面
示例,你需要输入:
字串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
了,现在我们开始建立示例发送程序和接收程序了:
// 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.QueueReceiver
receive()方法向队列同步请求消息。这可能阻塞接收程序,直到它不接收消息为止,或者如何某个消息没有在特定
时间间隔内到达而返回超时操作。第二种是一旦可以访问消息了就异步接收消息,使用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服务器简化了处理应用程序中
技术处理
过程;这样做更加灵活、容易扩展。
同样,对于聚焦于事务
应用程序,使用MQ技术也是非常方便
。这涉及到处理财政金融和新服务领域
一些应用程序。在财政金融市场,操作必须很快地完成;用户对于即时发生
改变感兴趣。 字串1
![我要研发网[www.51dev.com]](/templets/images/toplogo.gif)
