Sending a Message

JmsTemplate 包含许多便于发送消息的便捷方法。发送方法通过使用 jakarta.jms.Destination 对象指定目标,其他方法则通过在 JNDI 查找中使用 String 指定目标。不带目标参数的 send 方法使用默认目标。

The JmsTemplate contains many convenience methods to send a message. Send methods specify the destination by using a jakarta.jms.Destination object, and others specify the destination by using a String in a JNDI lookup. The send method that takes no destination argument uses the default destination.

下面的示例使用 MessageCreator 回调从提供的 Session 对象创建文本消息:

The following example uses the MessageCreator callback to create a text message from the supplied Session object:

import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.Queue;
import jakarta.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");
			}
		});
	}
}

在上述示例中,通过传递对 ConnectionFactory 的引用来构建 JmsTemplate。作为替代方案,提供了一个零参数构造函数和 connectionFactory,可用于在 JavaBean 样式中(使用 BeanFactory 或纯 Java 代码)构造实例。或者,考虑从 Spring 的 JmsGatewaySupport 便利基础类派生,它提供了用于 JMS 配置的预建 Bean 属性。

In the preceding example, the JmsTemplate is constructed by passing a reference to a ConnectionFactory. As an alternative, a zero-argument constructor and connectionFactory is provided and can be used for constructing the instance in JavaBean style (using a BeanFactory or plain Java code). Alternatively, consider deriving from Spring’s JmsGatewaySupport convenience base class, which provides pre-built bean properties for JMS configuration.

send(String destinationName, MessageCreator creator) 方法允许你通过使用目标字符串名称发送消息。如果这些名称在 JNDI 中注册,你应将模板的 destinationResolver 属性设置为 JndiDestinationResolver 的实例。

The send(String destinationName, MessageCreator creator) method lets you send a message by using the string name of the destination. If these names are registered in JNDI, you should set the destinationResolver property of the template to an instance of JndiDestinationResolver.

如果你创建了 JmsTemplate 并指定了默认目标,则 send(MessageCreator c) 会向该目标发送消息。

If you created the JmsTemplate and specified a default destination, the send(MessageCreator c) sends a message to that destination.

Using Message Converters

为了便于发送域模型对象,JmsTemplate 有各种发送方法,这些方法以 Java 对象作为消息数据内容的参数。convertAndSend()receiveAndConvert() 方法的重载方法在 JmsTemplate 中将转换过程委派给 MessageConverter`接口的实例。此接口定义了一个简单的约定来在 Java 对象和 JMS 消息之间转换。默认实现 (`SimpleMessageConverter) 支持 StringTextMessagebyte[] 和 `BytesMessage`以及 `java.util.Map`和 `MapMessage`之间的转换。通过使用转换器,你和应用程序代码可以关注通过 JMS 发送或接收的业务对象,而无需关注它如何表示为 JMS 消息的细节。

To facilitate the sending of domain model objects, the JmsTemplate has various send methods that take a Java object as an argument for a message’s data content. The overloaded methods convertAndSend() and receiveAndConvert() methods in JmsTemplate delegate the conversion process to an instance of the MessageConverter interface. This interface defines a simple contract to convert between Java objects and JMS messages. The default implementation (SimpleMessageConverter) supports conversion between String and TextMessage, byte[] and BytesMessage, and java.util.Map and MapMessage. By using the converter, you and your application code can focus on the business object that is being sent or received through JMS and not be concerned with the details of how it is represented as a JMS message.

沙箱当前包含一个 MapMessageConverter,它使用反射在 JavaBean 和 MapMessage 之间进行转换。你可能会自己实现的其他流行实现选择是使用现有的 XML 编组包(例如 JAXB 或 XStream)来创建表示对象的 TextMessage 的转换器。

The sandbox currently includes a MapMessageConverter, which uses reflection to convert between a JavaBean and a MapMessage. Other popular implementation choices you might implement yourself are converters that use an existing XML marshalling package (such as JAXB or XStream) to create a TextMessage that represents the object.

为了适应设置不能在转换器类内通用封装的消息的属性、报头和正文,MessagePostProcessor 接口让你在转换完消息但发送之前访问该消息。以下示例展示如何修改 java.util.Map 转换为消息之后的报头和属性:

To accommodate the setting of a message’s properties, headers, and body that can not be generically encapsulated inside a converter class, the MessagePostProcessor interface gives you access to the message after it has been converted but before it is sent. The following example shows how to modify a message header and a property after a java.util.Map is converted to a message:

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;
		}
	});
}

这会生成如下格式的消息:

This results in a message of the following form:

MapMessage={ Header={ ... standard headers ... CorrelationID={123-00001} } Properties={ AccountID={Integer:1234} } Fields={ Name={String:Mark} Age={Integer:47} } }

Using SessionCallback and ProducerCallback

虽然发送操作涵盖了许多常见的用例,但你可能有时希望对 JMS Session 或 MessageProducer 执行多个操作。SessionCallback 和 ProducerCallback 分别公开 JMS Session 和 Session/MessageProducer 对。JmsTemplate 上的 execute() 方法运行这些回调方法。

While the send operations cover many common usage scenarios, you might sometimes want to perform multiple operations on a JMS Session or MessageProducer. The SessionCallback and ProducerCallback expose the JMS Session and Session / MessageProducer pair, respectively. The execute() methods on JmsTemplate run these callback methods.