spring:
rabbitmq:
template:
exchange: tacocloud.orders
routing-key: kitchens.central
В этом случае все сообщения, отправленные без указания exchange, будут автоматически отправлены на exchange, имя которого - tacocloud.orders. Если ключ маршрутизации также не указан в вызове send() или convertAndSend(), у сообщений будет ключ маршрутизации kitchens.central.
Создать объект Message из конвертера сообщений достаточно просто, но еще проще использовать convertAndSend(), чтобы RabbitTemplate обрабатывал всю работу по преобразованию за вас:
public void sendOrder(Order order) {
rabbit.convertAndSend("tacocloud.order", order);
}
НАСТРОЙКА ПРЕОБРАЗОВАТЕЛЯ СООБЩЕНИЙ
По умолчанию преобразование сообщений выполняется с помощью SimpleMessageConverter, который может преобразовывать простые типы (например, String) и объекты Serializable в объекты Message. Но Spring предлагает несколько конвертеров сообщений для RabbitTemplate, включая следующие:
Jackson2JsonMessageConverter—Ковертирует объекты В и ИЗ JSON используя Jackson 2 JSON processor
MarshallingMessageConverter—Конвертирует используя Spring Marshaller и Unmarshaller
SerializerMessageConverter—Ковертирует String aи нативные объекты любого типа используя Spring-овый Serializer и Deserializer абстракции
SimpleMessageConverter - преобразует строки, байтовые массивы и Serializable типы.
ContentTypeDelegatingMessageConverter - делегирует другому MessageConverter на основе заголовка contentType.
MessagingMessageConverter - делегирует базовый MessageConverter для преобразования сообщений и AmqpHeaderConverter для заголовков.
Если вам нужно изменить конвертер сообщений, все, что вам нужно сделать, это настроить bean-компонент типа MessageConverter. Например, для преобразования сообщений на основе JSON вы можете настроить конвертер Jackson2JsonMessageConver следующим образом:
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
Автоконфигурация Spring Boot обнаружит этот bean-компонент и вставит его в RabbitTemplate вместо конвертера сообщений по умолчанию.
НАСТРОЙКА СВОЙСТВ СООБЩЕНИЙ
Как и в случае с JMS, вам может потребоваться установить некоторые заголовки в отправляемых вами сообщениях. Например, допустим, вам нужно отправить X_ORDER_SOURCE для всех заказов, представленных через веб-сайт Taco Cloud. При создании ваших собственных объектов Message вы можете установить заголовок через экземпляр MessageProperties, который вы передаете конвертеру сообщений. Возвращаясь к методу sendOrder() из листинга 8.5, вам понадобится всего одна дополнительная строка кода для установки заголовка:
public void sendOrder(Order order) {
MessageConverter converter = rabbit.getMessageConverter();
MessageProperties props = new MessageProperties();
props.setHeader("X_ORDER_SOURCE", "WEB");
Message message = converter.toMessage(order, props);
rabbit.send("tacocloud.order", message);
}
Однако при использовании convertAndSend() у вас нет быстрого доступа к объекту MessageProperties. В этом вам может помочь MessagePostProcessor:
@Override
public void sendOrder(Order order) {
rabbit.convertAndSend("tacocloud.order.queue", order,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message)
throws AmqpException {
MessageProperties props = message.getMessageProperties();
props.setHeader("X_ORDER_SOURCE", "WEB");
return message;
}
});
}
Здесь вы предоставляете convertAndSend() анонимной внутренней реализацией MessagePostProcessor. В методе postProcessMessage() вы извлекаете свойства MessageProperties из сообщения и затем вызываете setHeader(), чтобы установить заголовок X_ORDER_SOURCE.
Теперь, когда вы увидели, как отправлять сообщения с помощью RabbitTemplate, давайте переключимся на код, который получает сообщения из очереди RabbitMQ.
8.2.3 Получение сообщения от RabbitMQ
Вы видели, что отправка сообщений с помощью RabbitTemplate не сильно отличается от отправки сообщений с помощью JmsTemplate. И, как выясннится, получение сообщений из очереди RabbitMQ не сильно отличается от JMS.
Как и в случае с JMS, у вас есть два варианта:
-Получение сообщений из очереди с помощью RabbitTemplate
-Отправка сообщений в методе, аннотированным @RabbitListener.
Давайте начнем с рассмотрения pull-овского метода RabbitTemplate.receive(), основанного на извлечении.
ПОЛУЧЕНИЕ СООБЩЕНИЙ С RABBITTEMPLATE
RabbitTemplate поставляется с несколькими методами для извлечения сообщений из очереди. Несколько наиболее полезных из них перечислены здесь:
// Получение сообщений
Message receive() throws AmqpException;
Message receive(String queueName) throws AmqpException;
Message receive(long timeoutMillis) throws AmqpException;
Message receive(String queueName, long timeoutMillis) throws AmqpException;
// Получать объекты, преобразованные из сообщений
Object receiveAndConvert() throws AmqpException;
Object receiveAndConvert(String queueName) throws AmqpException;
Object receiveAndConvert(long timeoutMillis) throws AmqpException;
Object receiveAndConvert(String queueName, long timeoutMillis) throws
AmqpException;
// Получать типобезопасные объекты, преобразованные из сообщений
AmqpException;
throws AmqpException;
type) throws AmqpException;
ParameterizedTypeReference
Эти методы являются зеркальными изображениями методов send() и convertAndSend(), описанных ранее. Принимая во внимание, что send() используется для отправки необработанных объектов Message, а receive() получает необработанные объекты Message из очереди. Аналогично, receiveAndConvert() получает сообщения и использует конвертер сообщений для преобразования их в объекты домена перед их возвратом.
Но есть несколько очевидных различий в сигнатурах методов. Во-первых, ни один из этих методов не принимает ключ обмена или маршрутизации в качестве параметра. Это связано с тем, что обмены и ключи маршрутизации используются для маршрутизации сообщений в очереди, но как только сообщения находятся в очереди, их следующим пунктом назначения является потребитель, который вытаскивает их из очереди. Приложения-потребители не должны заниматься обменом или маршрутизацией ключей. Очередь - это единственное, что нужно знать приложениям-потребителям.
Вы также заметите, что многие методы принимают long параметр, указывающий тайм-аут для получения сообщений. По умолчанию время ожидания приема составляет 0 миллисекунд. То есть вызов метода receive() будет возвращен немедленно, потенциально с null значением, если сообщения недоступны. Это явное отличие от того, как ведут себя методы receive() в JmsTemplate. Передав значение тайм-аута, методы receive() и receiveAndConvert() блокируются до прибытия сообщения или до истечения времени ожидания. Но даже при ненулевом таймауте ваш код должен быть готов к null возврату.
Давайте посмотрим, как вы можете применить это на практике. Следующий листинг показывает новую реализацию OrderReceiver на основе Rabbit, которая использует RabbitTemplate для получения заказов.
Листинг 8.6. Получение заказов от RabbitMQ с помощью RabbitTemplate
package tacos.kitchen.messaging.rabbit;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RabbitOrderReceiver {
private RabbitTemplate rabbit;
private MessageConverter converter;
@Autowired
public RabbitOrderReceiver(RabbitTemplate rabbit) {
this.rabbit = rabbit;
this.converter = rabbit.getMessageConverter();
}
public Order receiveOrder() {
Message message = rabbit.receive("tacocloud.orders");
return message != null ? (Order) converter.fromMessage(message) : null;
}
}
Метод receiveOrder() - это место, где происходит все действие. Он вызывает метод receive() на внедренном шаблоне RabbitTemplate для получения заказа из очереди tacocloud.orders. Он не предоставляет значения времени ожидания, поэтому вы можете только предполагать, что вызов немедленно возвращается либо с Message, либо с null значением. Если Message возвращается, вы используете MessageConverter из шаблона RabbitTemplate для преобразования Message в Order. Иначе, если receive() возвращает null, вы возвращаете null.
В зависимости от варианта использования вы можете установить небольшую задержку. Например, на верхнем дисплее кухни Taco Cloud вы можете подождать некоторое время, если нет заказов. Допустим, вы решили подождать до 30 секунд, прежде чем сдаться. Метод receiveOrder() может быть изменен для передачи 30 000 миллисекундной задержки для receive():