Выбрать главу

    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 (извлечения) модель позволяет потребителю заявить, что он готов обработать новое сообщение.