Map<String, Class<?>> typeIdMappings = new HashMap<String, Class<?>>();
typeIdMappings.put("order", Order.class);
messageConverter.setTypeIdMappings(typeIdMappings);
return messageConverter;
}
Вместо того, чтобы полное имя класса отправлялось в свойстве _typeId сообщения, будет отправлено значение order. В принимающем приложении будет сконфигурирован аналогичный конвертер сообщений, отображающий order в собственном понимании order-а. Эта реализация order может быть в другом пакете, иметь другое имя и даже иметь подмножество свойств Order отправителя.
POST-ОБРАБОТКА СООБЩЕНИЙ
Предположим, что в дополнение к своему прибыльному веб-бизнесу Taco Cloud решила открыть несколько магазинов в строительном секторе. Учитывая, что любой из их ресторанов также может быть центром для веб-бизнеса, им нужен способ сообщить источник заказа на кухню в ресторан. Это позволит кухонному персоналу использовать другой процесс для заказов в магазине, нежели для заказов через Интернет.
Было бы разумно добавить новое свойство источника в объект Order для переноса этой информации, установв его как WEB для заказов, размещенных в Интернете, и STORE для заказов, размещенных в магазинах. Но для этого потребуется изменить как класс Order на веб-сайте, так и класс Order для кухонного приложения, когда на самом деле это информация, которая требуется только для составителей тако.
Более простым решением было бы добавить пользовательский заголовок к сообщению для установки источника заказа. Если бы вы использовали метод send() для отправки тако-заказов, это можно легко сделать, вызвав setStringProperty() для объекта Message:
jms.send("tacocloud.order.queue",
session -> {
Message message = session.createObjectMessage(order);
message.setStringProperty("X_ORDER_SOURCE", "WEB");
});
Проблема в том, что вы не используете send(). При выборе использования convertAndSend() объект Message создается в обертке, и у вас нет к нему доступа.
К счастью, есть способ настроить Message, созданное в обертке, до его отправки. Передав MessagePostProcessor в качестве последнего параметра для convertAndSend(), вы можете делать с сообщением все, что захотите, после его создания. Следующий код по-прежнему использует convertAndSend(), но использует MessagePostProcessor для добавления заголовка X_ORDER_SOURCE до отправки сообщения:
jms.convertAndSend("tacocloud.order.queue", order, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws JMSException {
message.setStringProperty("X_ORDER_SOURCE", "WEB");
return message;
}
});
Возможно, вы заметили, что MessagePostProcessor - это функциональный интерфейс. Это означает, что вы можете немного упростить его, заменив анонимный внутренний класс лямбда-выражением:
jms.convertAndSend("tacocloud.order.queue", order,
message -> {
message.setStringProperty("X_ORDER_SOURCE", "WEB");
return message;
});
Хотя вам нужен только этот конкретный MessagePostProcessor для этого одного вызова метода convertAndSend(), вы можете использовать один и тот же MessagePostProcessor для нескольких различных вызовов convertAndSend(). В этих случаях, возможно, ссылка на метод является лучшим выбором, чем лямбда, во избежание ненужного дублирования кода:
@GetMapping("/convertAndSend/order")
public String convertAndSendOrder() {
Order order = buildOrder();
jms.convertAndSend("tacocloud.order.queue", order,
this::addOrderSource);
return "Convert and sent order";
}
private Message addOrderSource(Message message) throws JMSException {
message.setStringProperty("X_ORDER_SOURCE", "WEB");
return message;
}
Теперь вы видели несколько способов отправки сообщений. Но не стоит отправлять сообщение, если никто его не получит. Давайте посмотрим, как вы можете получать сообщения с помощью Spring и JMS.
8.1.3 Получение JMS сообщений
Когда дело доходит до получения сообщений, у вас есть выбор pull (получения) модель, где ваш код запрашивает сообщение и ожидает его получение, или push (проталкивания) модель, в которой сообщения передаются в ваш код по мере их поступления.
JmsTemplate предлагает несколько методов для получения сообщений, но все они используют pull модель. Вы вызываете один из этих методов для запроса сообщения, и поток блокируется до тех пор, пока сообщение не станет доступным (что может быть немедленно или может занять некоторое время).
С другой стороны, у вас также есть возможность использовать push-модель, в которой вы определяете слушатель (listener) сообщений, который вызывается каждый раз, когда сообщение доступно.
Оба варианта подходят для различных вариантов использования. Общепринято, что push-модель - лучший выбор, так как она не блокирует поток. Но в некоторых случаях использование слушателя (listener) может быть перегружено, если сообщения приходят слишком быстро. Pull (извлечения) модель позволяет потребителю заявить, что он готов обработать новое сообщение.