Три метода send() требуют, чтобы MessageCreator создал объект Message.
Три метода convertAndSend() принимают Object и автоматически преобразуют этот Object в Message.
Три метода convertAndSend() автоматически преобразуют Object в Message, но также принимают MessagePostProcessor, позволяющий настроить Message до его отправки.
Кроме того, каждая из этих трех категорий методов состоит из трех переопределяющих методов, которые различаются тем, как указывается место назначения JMS (очередь или тема):
Один метод не принимает параметр пункта назначения и отправляет сообщение в пункт назначения по умолчанию.
Один метод принимает объект Destination, который указывает место назначения для сообщения.
Один метод принимает String, которая указывает место назначения для сообщения по наименованию.
Чтобы эти методы работали, рассмотрим JmsOrderMessagingService в следующем листинге, который использует самую основную форму метода send().
Листинг 8.1. Отправка заказа с помощью .send() в пункт назначения по умолчанию
package tacos.messaging;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;
@Service
public class JmsOrderMessagingService implements OrderMessagingService {
private JmsTemplate jms;
@Autowired
public JmsOrderMessagingService(JmsTemplate jms) {
this.jms = jms;
}
@Override
public void sendOrder(Order order) {
jms.send(new MessageCreator() {
@Override
public Message createMessage(Session session)
throws JMSException {
return session.createObjectMessage(order);
}
}
);
}
}
Метод sendOrder() вызывает jms.send(), передавая анонимную внутреннюю реализацию класса MessageCreator. Эта реализация переопределяет createMessage() для создания нового сообщения объекта из заданного объекта Order.
Я не уверен насчет вас, но я думаю, что код в листинге 8.1, хотя и простой, немного неуклюжий. Церемония, связанная с объявлением анонимного внутреннего класса, усложняет простой вызов метода. Признавая, что MessageCreator является функциональным интерфейсом, вы можете немного привести в порядок метод sendOrder() с помощью лямбды:
@Override
public void sendOrder(Order order) {
jms.send(session -> session.createObjectMessage(order));
}
Но обратите внимание, что вызов jms.send() не указывает адресата. Чтобы это работало, вы также должны указать имя получателя по умолчанию в свойстве spring.jms.template.default-destination. Например, вы можете установить свойство в вашем файле application.yml следующим образом:
spring:
jms:
template:
default-destination: tacocloud.order.queue
Во многих случаях использование пункта назначения по умолчанию является самым простым выбором. Это позволяет вам указать имя получателя один раз, позволяя коду относиться только к отправке сообщений, независимо от того, куда они отправляются. Но если вам когда-либо понадобится отправить сообщение в пункт назначения, отличный от пункта назначения по умолчанию, вам нужно будет указать этот пункт назначения в качестве параметра send().
Один из способов сделать это - передать объект Destination в качестве первого параметра send(). Самый простой способ сделать это - объявить bean-объект Destination, а затем внедрить его в bean-компонент, выполняющий обмен сообщениями. Например, следующий bean-компонент объявляет Destination очереди Taco Cloud:
@Bean
public Destination orderQueue() {
return new ActiveMQQueue("tacocloud.order.queue");
}
Важно отметить, что ActiveMQQueue, использованный здесь, на самом деле от Artemis (из пакета org.apache.activemq.artemis.jms.client). Если вы используете ActiveMQ (не Artemis), есть также класс с именем ActiveMQQueue (из пакета org.apache.activemq.command).
Если этот целевой объект внедряется в JmsOrderMessagingService, вы можете использовать его для указания получателя при вызове send():
private Destination orderQueue;
@Autowired
public JmsOrderMessagingService(JmsTemplate jms, Destination orderQueue) {
this.jms = jms;
this.orderQueue = orderQueue;
}
...
@Override
public void sendOrder(Order order) {
jms.send(
orderQueue,
session -> session.createObjectMessage(order));
}
Указание адресата с помощью объекта Destination, подобного этому, дает вам возможность настроить Destination с использованием не только имени пункта назначения. Но на практике вы почти никогда не будете указывать ничего, кроме имени пункта назначения. Часто проще просто отправить имя в качестве первого параметра send():