傳送訊息
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) 支援 String 和 TextMessage、byte[] 和 BytesMessage 以及 java.util.Map 和 MapMessage 之間的轉換。透過使用轉換器,您和您的應用程式程式碼可以專注於透過 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.TextMessage、jakarta.jms.BytesMessage 等。對於支援通用訊息負載的契約,請使用 org.springframework.messaging.converter.MessageConverter 結合 JmsMessagingTemplate 或更優選的 JmsClient 作為您的中心委託。 |
在 JmsTemplate 上使用 SessionCallback 和 ProducerCallback
雖然傳送操作涵蓋了許多常見的用法場景,但有時您可能希望對 JMS Session 或 MessageProducer 執行多個操作。SessionCallback 和 ProducerCallback 分別公開了 JMS Session 和 Session / 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 Message 的 org.springframework.messaging.core.MessagePostProcessor 可以在 JmsClient 上進行配置,實現此功能。它將用於所有透過 send 和 sendAndReceive 方法傳送的出站訊息。
這是一個攔截器示例,它為所有出站訊息添加了一個“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();
}
}
}