2.4 JMS规范
就像前面提到的,JMS规范定义了两种客户端--JMS客户端和非JMS客户端。它们之间的区别必须简单讨论下。
2.4.1 JMS客户端
JMS客户端使用JMS API与JMS提供者交互。就像使用JDBC API去访问关系数据库一样,JMS客户端使用JMS API作为消息驱动服务的标准访问方式。许多JMS提供者(包括ActiveMQ)包含了很多超出JMS规范要求的特性。值得一提的是一个100%JMS客户端只能使用JMS提供的API,必须避免使用额外的特性。不过一般选择哪个JMS provider通常是由它提供的额外特性决定的。所以,一个使用了额外特性的JMS客户端,如果不重构,可能就不能用于其它JMS provider。
JMS clients使用MessageProducer(消息生产者)和MessageConsumer(消息消费者)接口。JMS provider必须提供这些接口的实现。JMS client如果发送消息,那么它就是producer(生产者),如果接收消息,那么它就是Consumer(消费者)。JMS client也有可能同时发送和接收消息。
JMS PRODUCERS
JMS clients使用JMS MessageProducer类来发送消息到一个destination。当调用Session.createProducer产生一个producer时,将会有默认的destination。不过这个可以通过重写MessageProducer.send()方法来改变。MessageProducer接口如下所示。
Listing 2.1 The MessageProducer interface
public interface MessageProducer {
void setDisableMessageID(boolean value) throws JMSException;
boolean getDisableMessageID() throws JMSException;
void setDisableMessageTimestamp(boolean value) throws JMSException;
boolean getDisableMessageTimestamp() throws JMSException;
void setDeliveryMode(int deliveryMode) throws JMSException;
int getDeliveryMode() throws JMSException;
void setPriority(int defaultPriority) throws JMSException;
int getPriority() throws JMSException;
void setTimeToLive(long timeToLive) throws JMSException;
long getTimeToLive() throws JMSException;
Destination getDestination() throws JMSException;
void close() throws JMSException;
void send(Message message) throws JMSException;
void send(Message message, int deliveryMode, int priority,
long timeToLive)
throws JMSException;
void send(Destination destination, Message message)
throws JMSException;
void send(
Destination destination,
Message message,
int deliveryMode,
int priority,
long timeToLive)
throws JMSException;
}
MessageProducer提供了发送消息的和设置消息头部的方法。消息头部设置包括JMSDeliveryMode(投递类型),JMSPriority(优先级),JMSExpiration(有效期,通过get/setTimeLive()设置)以及一个同时设置前面三种消息头的方法send()。这些消息头部将在2.4.5讲解。
JMS CONSUMERS
JMS客户端使用JMS MessageConsumer类从一个destionation消费消息。它可以通过receive()方法同步地消费消息,也可以通过提供一个MessageListener实现来异步地消费消息。MessageListener.onMessage()方法会在消息到达destination时被调用。MessageConsumer接口如下所示。
Listing 2.2 The JMS MessageConsumer interface
public interface MessageConsumer {
String getMessageSelector() throws JMSException;
MessageListener getMessageListener() throws JMSException;
void setMessageListener(MessageListener listener) throws JMSException;
Message receive() throws JMSException;
Message receive(long timeout) throws JMSException;
Message receiveNoWait() throws JMSException;
void close() throws JMSException;
}
接口中没有方法为MessageConsumer设置destination。事实上,destination会在使用Session.createConsumer()创建Consumer的时候被设置。
2.4.2 Non-JMS clients
就像先前提到的Non-JMS客户端使用JMS provider本地的客户端API,而不是使用JMS API。这是个重要的区别,因为本地的客户端API可能提供一些不同的特性。这类本地non-JMS API能够在Java RMI上面使用CORBA IIOP协议或其它一些本地协议。在JMS规范出来之前的一些消息provider通常有本地的客户端API,之后,也有很多JMS provider提供本地的API。
2.4.3 The JMS provider
JMS provider是一个由供应商提供的JMS API实现。它们提供标准的JMS API来访问MOM。(这和JDBC类似)
2.4.4 The JMS message
JMS消息是JMS规范最重要的一个概念。JMS规范所有其它概念都是围绕消息处理而建立的,因为消息是商业数据和事件的载体。JMS消息能够传输任何的数据,包括文本,二进制数和以及在消息头的信息等。如何2.5,JMS消息包含两部分,包括消息头和负载(payload)。消息头为客户端和JMS provider提供消息的元数据。payload事实上就是消息体,可以通过各种消息类型,存放文本和二进制数据。
JMS消息被设计为容易理解和变通。所有复杂的东西都留在消息头部。