26.3 发送消息
JmsTemplate
包含许多方便的方法来发送消息。有些发送方法可以使用 javax.jms.Destination
对象指定目的地,也可以使用字符串在 JNDI 中查找目的地。没有目的地参数的发送方法使用默认的目的地。
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Session;
import org.springframework.jms.core.MessageCreator;
import org.springframework.jms.core.JmsTemplate;
public class JmsQueueSender {
private JmsTemplate jmsTemplate;
private Queue queue;
public void setConnectionFactory(ConnectionFactory cf) {
this.jmsTemplate = new JmsTemplate(cf);
}
public void setQueue(Queue queue) {
this.queue = queue;
}
public void simpleSend() {
this.jmsTemplate.send(this.queue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("hello queue world");
}
});
}
}
这个例子使用MessageCreator
回调接口从提供的会话对象中创建一个文本消息,并且通过一个ConnectionFactory
的引用来构造JmsTemplate
。或者,提供了一个无参数的构造方法和connectionFactory
,并可用于以 JavaBean 方式构建实例(使用 BeanFactory 或纯 Java 代码)。或者考虑从 Spring 的基类JmsGatewaySupport
派生,它对 JMS 配置具有内置的 bean 属性。
方法send(String destinationName,MessageCreator creator)
让你利用目的地的字符串名称发送消息。如果这些名称在 JNDI 中注册,则应将模板的destinationResolver
属性设置为JndiDestinationResolver
的一个实例。
如果创建了JmsTemplate
并指定一个默认的目的地,那么send(MessageCreator c)
会向该目的地发送消息。
26.3.1 使用消息转换器
为便于发送领域模型对象,JmsTemplate
有多种以一个 Java 对象为参数并做为发送消息的数据内容。JmsTemplate
里可重载的方法convertAndSend
和receiveAndConvert
将转换的过程委托给接口MessageConverter
的一个实例。这个接口定义了一个简单的合约用来在 Java 对象和 JMS 消息间进行转换。缺省的实现SimpleMessageConverter
支持String
和TextMessage
,byte[]
和BytesMesssage
,以及java.util.Map
和MapMessage
之间的转换。使用转换器,可以使你和你的应用关注于通过 JMS 接收和发送的业务对象而不用操心它是具体如何表达成 JMS 消息的。
目前的沙箱模型包括一个MapMessageConverter
,它使用反射转换 JavaBean 和MapMessage
。其他流行可选的实现方式包括使用已存在的 XML 编组的包(如 JAXB,Castor 或 XStream)来创建一个表示对象的TextMessage
。
为方便那些不能以通用方式封装在转换类里的消息属性、消息头和消息体的设置,通过MessagePostProcessor
接口,你可以在消息被转换后并且在发送前访问该消息。下例展示了如何在java.util.Map
已经转换成一个消息后更改消息头和属性。
public void sendWithConversion() {
Map map = new HashMap();
map.put("Name", "Mark");
map.put("Age", new Integer(47));
jmsTemplate.convertAndSend("testQueue", map, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws JMSException {
message.setIntProperty("AccountID", 1234);
message.setJMSCorrelationID("123-00001");
return message;
}
});
}
这将产生一个如下的消息格式:
MapMessage={
Header={
... standard headers ...
CorrelationID={123-00001}
}
Properties={
AccountID={Integer:1234}
}
Fields={
Name={String:Mark}
Age={Integer:47}
}
}
26.3.2 SessionCallback和ProducerCallback
虽然 send 操作适用于许多常见的使用场景,但是有时你需要在一个 JMS 会话(Session
) 或者MessageProducer
上执行多个操作。接口SessionCallback
和ProducerCallback
分别提供了 JMS Session 和 Session / MessageProducer 对。在JmsTemplate
上的execute()
方法执行这些回调方法。