26.3 发送消息

JmsTemplate包含许多方便的方法来发送消息。有些发送方法可以使用 javax.jms.Destination对象指定目的地,也可以使用字符串在 JNDI 中查找目的地。没有目的地参数的发送方法使用默认的目的地。

  1. import javax.jms.ConnectionFactory;
  2. import javax.jms.JMSException;
  3. import javax.jms.Message;
  4. import javax.jms.Queue;
  5. import javax.jms.Session;
  6. import org.springframework.jms.core.MessageCreator;
  7. import org.springframework.jms.core.JmsTemplate;
  8. public class JmsQueueSender {
  9. private JmsTemplate jmsTemplate;
  10. private Queue queue;
  11. public void setConnectionFactory(ConnectionFactory cf) {
  12. this.jmsTemplate = new JmsTemplate(cf);
  13. }
  14. public void setQueue(Queue queue) {
  15. this.queue = queue;
  16. }
  17. public void simpleSend() {
  18. this.jmsTemplate.send(this.queue, new MessageCreator() {
  19. public Message createMessage(Session session) throws JMSException {
  20. return session.createTextMessage("hello queue world");
  21. }
  22. });
  23. }
  24. }

这个例子使用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里可重载的方法convertAndSendreceiveAndConvert将转换的过程委托给接口MessageConverter的一个实例。这个接口定义了一个简单的合约用来在 Java 对象和 JMS 消息间进行转换。缺省的实现SimpleMessageConverter支持StringTextMessagebyte[]BytesMesssage,以及java.util.MapMapMessage之间的转换。使用转换器,可以使你和你的应用关注于通过 JMS 接收和发送的业务对象而不用操心它是具体如何表达成 JMS 消息的。

目前的沙箱模型包括一个MapMessageConverter,它使用反射转换 JavaBean 和MapMessage。其他流行可选的实现方式包括使用已存在的 XML 编组的包(如 JAXB,Castor 或 XStream)来创建一个表示对象的TextMessage

为方便那些不能以通用方式封装在转换类里的消息属性、消息头和消息体的设置,通过MessagePostProcessor接口,你可以在消息被转换后并且在发送前访问该消息。下例展示了如何在java.util.Map已经转换成一个消息后更改消息头和属性。

  1. public void sendWithConversion() {
  2. Map map = new HashMap();
  3. map.put("Name", "Mark");
  4. map.put("Age", new Integer(47));
  5. jmsTemplate.convertAndSend("testQueue", map, new MessagePostProcessor() {
  6. public Message postProcessMessage(Message message) throws JMSException {
  7. message.setIntProperty("AccountID", 1234);
  8. message.setJMSCorrelationID("123-00001");
  9. return message;
  10. }
  11. });
  12. }

这将产生一个如下的消息格式:

  1. MapMessage={
  2. Header={
  3. ... standard headers ...
  4. CorrelationID={123-00001}
  5. }
  6. Properties={
  7. AccountID={Integer:1234}
  8. }
  9. Fields={
  10. Name={String:Mark}
  11. Age={Integer:47}
  12. }
  13. }

26.3.2 SessionCallback和ProducerCallback

虽然 send 操作适用于许多常见的使用场景,但是有时你需要在一个 JMS 会话(Session) 或者MessageProducer上执行多个操作。接口SessionCallbackProducerCallback分别提供了 JMS Session 和 Session / MessageProducer 对。在JmsTemplate上的execute()方法执行这些回调方法。