artemis:
host: artemis.tacocloud.com
port: 61617
user: tacoweb
password: l3tm31n
Это настраивает Spring для создания подключений к брокеру Artemis, который прослушивает artemis.tacocloud.com, порт 61617. Он также устанавливает учетные данные для приложения, которое будет взаимодействовать с этим брокером. Учетные данные не являются обязательными, но они рекомендуются для рабочих развертываний.
Если бы вы использовали ActiveMQ вместо Artemis, вам нужно было бы использовать специфичные для ActiveMQ свойства, перечисленные в таблице 8.2.
Таблица 8.2 Свойства для настройки расположения и учетных данных брокера ActiveMQ
Свойство - Описание
spring.activemq.broker-url - URL broker-а
spring.activemq.user - user использующийся для доступа к broker (опционально)
spring.activemq.password - password использующийся для доступа к broker (опционально)
spring.activemq.in-memory - Стоит ли запускать брокер в памяти (по умолчанию: true)
Обратите внимание, что вместо того, чтобы предлагать отдельные свойства для имени хоста и порта брокера (посредника), адрес брокера ActiveMQ указывается с помощью одного свойства, spring.activemq.broker-url. URL должен быть tcp://URL , как показано в следующем фрагменте YAML:
spring:
activemq:
broker-url: tcp://activemq.tacocloud.com
user: tacoweb
password: l3tm31n
Независимо от того, выбираете ли вы Artemis или ActiveMQ, вам не нужно настраивать эти свойства для разработки, когда брокер работает локально.
Если вы используете ActiveMQ, вам, однако, необходимо установить для свойства spring.activemq.in-memory значение false, чтобы Spring не запускал брокер в памяти. Брокер в памяти может показаться полезным, но он полезен только тогда, когда вы будете использовать сообщения из того же приложения, которое их публикует (что имеет ограниченную полезность).
Вместо использования встроенного брокера вы должны установить и запустить брокера Artemis (или ActiveMQ), прежде чем двигаться дальше. Вместо того, чтобы повторять инструкции по установке здесь, я отсылаю вас к документации брокера:
Artemis—https://activemq.apache.org/artemis/docs/latest/using-server.html
ActiveMQ—http://activemq.apache.org/getting-started.html#GettingStarted-Pre-InstallationRequirements
С JMS-стартером в вашей сборке и брокером, ожидающим пересылки сообщений из одного приложения в другое, вы готовы начать отправку сообщений.
8.1.2 Отправка сообщений с помощью JmsTemplate
С JMS starter зависимостью (Artemis или ActiveMQ) в вашей сборке Spring Boot автоматически настроит JmsTemplate (среди прочего), который вы можете внедрить и использовать для отправки и получения
JmsTemplate является центральным элементом поддержки интеграции Spring JMS. Подобно другим шаблонно-ориентированным компонентам Spring, JmsTemplate устраняет много стандартного кода, который в противном случае потребовался бы для работы с JMS. Без JmsTemplate вам нужно было бы написать код для создания соединения и сеанса с брокером сообщений, а также дополнительный код для обработки любых исключений, которые могут возникнуть в процессе отправки сообщения. JmsTemplate фокусируется на том, что вы действительно хотите сделать: отправить сообщение.
JmsTemplate имеет несколько методов, которые полезны для отправки сообщений, включая следующие:
// Отправка сырых (raw) сообщений
void send(MessageCreator messageCreator) throws JmsException;
void send(Destination destination, MessageCreator messageCreator) throws JmsException;
void send(String destinationName, MessageCreator messageCreator) throws JmsException;
// Отправка сообщений сконвертированных из объектов
void convertAndSend(Object message) throws JmsException;
void convertAndSend(Destination destination, Object message) throws JmsException;
void convertAndSend(String destinationName, Object message) throws JmsException;
// Отправка сообщений, преобразованных из объектов с post-обработкойvoid convertAndSend(Object message,
MessagePostProcessor postProcessor) throws JmsException;
void convertAndSend(Destination destination, Object message,
MessagePostProcessor postProcessor) throws JmsException;
void convertAndSend(String destinationName, Object message,
MessagePostProcessor postProcessor) throws JmsException;
Как видите, на самом деле есть только два метода, send() и convertAndSend(), каждый из которых переопределен для поддержки различных параметров. И если вы посмотрите поближе, вы заметите, что различные формы convertAndSend() можно разбить на две подкатегории. Чтобы понять, что делают все эти методы, рассмотрим следующий список:
Три метода 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
publicDestinationorderQueue() {
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;
}