发送消息

JmsTemplate 包含许多方便的发送消息方法。一些发送方法使用 jakarta.jms.Destination 对象指定目的地,另一些则使用 JNDI 查找中的 String 指定目的地。不带目的地参数的 send 方法使用默认目的地。

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

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

在前面的例子中,JmsTemplate 是通过传递 ConnectionFactory 的引用来构造的。作为替代方案,提供了一个无参构造函数和 connectionFactory,可用于以 JavaBean 风格(使用 BeanFactory 或纯 Java 代码)构造实例。或者,考虑从 Spring 的 JmsGatewaySupport 便利基类派生,它提供了用于 JMS 配置的预构建 bean 属性。

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

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

使用 JMS 消息转换器

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

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

为了适应设置消息的属性、头部和正文(这些无法通用地封装在转换器类中),MessagePostProcessor 接口允许您在消息被转换后但在发送前访问它。以下示例展示了如何在 java.util.Map 转换为消息后修改消息头部和属性:

import java.util.HashMap;
import java.util.Map;

import jakarta.jms.JMSException;
import jakarta.jms.Message;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessagePostProcessor;

public class JmsSenderWithConversion {

	private JmsTemplate jmsTemplate;

	public void sendWithConversion() {
		Map<String, Object> map = new HashMap<>();
		map.put("Name", "Mark");
		map.put("Age", 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}
	}
}
这种 JMS 特定的 org.springframework.jms.support.converter.MessageConverter 安排操作 JMS 消息类型,并负责立即转换为 jakarta.jms.TextMessagejakarta.jms.BytesMessage 等。对于支持通用消息负载的契约,请使用 org.springframework.messaging.converter.MessageConverter 结合 JmsMessagingTemplate 或更优选的 JmsClient 作为您的中心委托。

JmsTemplate 上使用 SessionCallbackProducerCallback

虽然发送操作涵盖了许多常见的用法场景,但有时您可能希望对 JMS SessionMessageProducer 执行多个操作。SessionCallbackProducerCallback 分别公开了 JMS SessionSession / MessageProducer 对。JmsTemplate 上的 execute() 方法会运行这些回调方法。

使用 JmsClient 发送消息

import jakarta.jms.ConnectionFactory;

import org.springframework.jms.core.JmsClient;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

public class JmsClientSample {

	private final JmsClient jmsClient;

	public JmsClientSample(ConnectionFactory connectionFactory) {
		// For custom options, use JmsClient.builder(ConnectionFactory)
		this.jmsClient = JmsClient.create(connectionFactory);
	}

	public void sendWithConversion() {
		this.jmsClient.destination("myQueue")
				.withTimeToLive(1000)
				.send("myPayload");  // optionally with a headers Map next to the payload
	}

	public void sendCustomMessage() {
		Message<?> message = MessageBuilder.withPayload("myPayload").build();  // optionally with headers
		this.jmsClient.destination("myQueue")
				.withTimeToLive(1000)
				.send(message);
	}
}

后处理出站消息

应用程序通常需要在消息发送出去之前进行拦截,例如为所有出站消息添加消息属性。基于 spring-messaging Messageorg.springframework.messaging.core.MessagePostProcessor 可以在 JmsClient 上进行配置,实现此功能。它将用于所有通过 sendsendAndReceive 方法发送的出站消息。

这是一个拦截器示例,它为所有出站消息添加了一个“tenantId”属性。

import jakarta.jms.ConnectionFactory;

import org.springframework.jms.core.JmsClient;
import org.springframework.messaging.Message;
import org.springframework.messaging.core.MessagePostProcessor;
import org.springframework.messaging.support.MessageBuilder;

public class JmsClientWithPostProcessor {

	private final JmsClient jmsClient;

	public JmsClientWithPostProcessor(ConnectionFactory connectionFactory) {
		this.jmsClient = JmsClient.builder(connectionFactory)
				.messagePostProcessor(new TenantIdMessageInterceptor("42"))
				.build();
	}

	public void sendWithPostProcessor() {
		this.jmsClient.destination("myQueue")
				.withTimeToLive(1000)
				.send("myPayload");
	}

	static class TenantIdMessageInterceptor implements MessagePostProcessor {

		private final String tenantId;

		public TenantIdMessageInterceptor(String tenantId) {
			this.tenantId = tenantId;
		}

		@Override
		public Message<?> postProcessMessage(Message<?> message) {
			return MessageBuilder.fromMessage(message)
					.setHeader("tenantId", this.tenantId)
					.build();
		}
	}
}
© . This site is unofficial and not affiliated with VMware.