Давайте рассмотрим оба способа получения сообщений. Начнем с pull модели, предлагаемой JmsTemplate.
ПОЛУЧЕНИЕ С JmsTemplate
JmsTemplate предлагает несколько методов для методов извлечения из брокера, включая следующие:
Message receive() throws JmsException;
Message receive(Destination destination) throws JmsException;
Message receive(String destinationName) throws JmsException;
Object receiveAndConvert() throws JmsException;
Object receiveAndConvert(Destination destination) throws JmsException;
Object receiveAndConvert(String destinationName) throws JmsException;
Как видите, эти шесть методов отражение методов send() и convertAndSend () из JmsTemplate. Методы receive() получают необработанное Message, а методы receiveAndConvert() используют сконфигурированный конвертер сообщений для преобразования сообщений в типы доменов. И для каждого из них вы можете указать либо Destination, либо String, содержащую имя пункта назначения, или вы можете получить сообщение из пункта назначения по умолчанию.
Чтобы увидеть их в действии, вы напишите некоторый код, который извлекает Order из пункта назначения tacocloud.order.queue. В следующем листинге показан OrderReceiver, компонент службы, который получает данные заказа с помощью JmsTemplate.receive().
Листинг 8.2. Получение заказов из очереди
package tacos.kitchen.messaging.jms;
import javax.jms.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.stereotype.Component;
@Component
public class JmsOrderReceiver implements OrderReceiver {
private JmsTemplate jms;
private MessageConverter converter;
@Autowired
public JmsOrderReceiver(JmsTemplate jms, MessageConverter converter) {
this.jms = jms;
this.converter = converter;
}
public Order receiveOrder() {
Message message = jms.receive("tacocloud.order.queue");
return (Order) converter.fromMessage(message);
}
}
Здесь вы использовали String, чтобы указать пункт назначения для получения заказа. Метод receive() возвращает не конвертированный Message. Нам нужен Order, который находится внутри, Message, поэтому следующее, что происходит, - это использование конвертера сообщения для его преобразования. Свойство type ID в сообщении поможет конвертеру преобразовать его в Order, но ответ будет в виде Object, который придется привести к нужному типу перед тем, как вы сможете его вернуть.
Получение необработанного объекта Message может быть полезно в некоторых случаях, когда вам необходимо проверить свойства и заголовки сообщения. Но часто вам нужна только полезная нагрузка. Преобразование этой полезной нагрузки в тип домена является двухэтапным процессом и требует, чтобы преобразователь сообщений был внедрен в компонент. Когда вы заботитесь только о полезной нагрузке сообщения, использовать receiveAndConvert() будет намного проще. В следующем листинге показано, как JmsOrderReceiver может быть переработан для использования receiveAndConvert () вместо receive().
Листинг 8.3 Получение преобразованного объекта Order
package tacos.kitchen.messaging.jms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component
public class JmsOrderReceiver implements OrderReceiver {
private JmsTemplate jms;
@Autowired
public JmsOrderReceiver(JmsTemplate jms) {
this.jms = jms;
}
public Order receiveOrder() {
return (Order) jms.receiveAndConvert("tacocloud.order.queue");
}
}
Эта новая версия JmsOrderReceiver имеет метод receieveOrder (), который был сокращен до одной строки. И вам больше не нужно внедрять MessageConverter, потому что все преобразования сообщений будут выполняться под капотом в receiveAndConvert ().
Прежде чем двигаться дальше, давайте рассмотрим, как receiveOrder() может быть использован в кухонном приложении Taco Cloud. Повар на одной из кухонь Taco Cloud может нажать кнопку или предпринять какие-либо действия, чтобы указать, что они готовы начать создание тако. В этот момент будет вызван receiveOrder(), и вызов метода receive() или receiveAndConvert() будет заблокирован. Больше ничего не произойдет, пока сообщение о заказе не будет готово. Как только заказ поступит, он будет возвращен функцией receiveOrder(), и его информация будет использоваться для отображения деталей заказа, чтобы повар мог приступить к работе. Это кажется естественным выбором для модели тянуть (pull).