Перейти к основному содержимому

Начало работы с Spring JMS

· 6 мин. чтения

1. Обзор

Spring предоставляет среду интеграции JMS, которая упрощает использование JMS API. В данной статье представлены основные понятия такой интеграции.

2. Зависимость от Maven

Чтобы использовать Spring JMS в нашем приложении, нам нужно добавить необходимые артефакты в pom.xml :

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>

Новейшую версию артефакта можно найти здесь .

3. Шаблон Jms

Класс JmsTemplate обрабатывает создание и освобождение ресурсов при отправке или синхронном получении сообщений.

Следовательно, класс, который использует этот JmsTemplate , должен только реализовать интерфейсы обратного вызова, как указано в определении метода.

Начиная с Spring 4.1, JmsMessagingTemplate строится поверх JmsTemplate , который обеспечивает интеграцию с абстракцией обмена сообщениями, т . е . org.springframework.messaging.Message. Это, в свою очередь, позволяет нам создать сообщение для отправки в общем виде.

4. Управление подключением

Чтобы подключиться и иметь возможность отправлять/получать сообщения, нам нужно настроить ConnectionFactory .

ConnectionFactory — это один из администрируемых объектов JMS, который предварительно настраивается администратором . Клиент с помощью конфигурации установит соединение с провайдером JMS.

Spring предоставляет 2 типа ConnectionFactory :

  • SingleConnectionFactory — это реализация интерфейса ConnectionFactory , которая будет возвращать одно и то же соединение при всех вызовах createConnection () и игнорировать вызовы close ()
  • CachingConnectionFactory расширяет функциональность SingleConnectionFactory и добавляет кеширование Sessions , MessageProducers и MessageConsumers.

5. Управление пунктом назначения

Как обсуждалось выше, наряду с ConnectionFactory адресаты также являются администрируемыми объектами JMS и могут храниться и извлекаться из JNDI.

Spring предоставляет общие преобразователи, такие как DynamicDestinationResolver, и специальные преобразователи, такие как JndiDestinationResolver .

JmsTemplate делегирует разрешение имени назначения одной из реализаций на основе нашего выбора.

Он также предоставит свойство с именем defaultDestination , которое будет использоваться с операциями отправки и получения , не относящимися к конкретному месту назначения.

6. Преобразование сообщений

Spring JMS был бы неполным без поддержки преобразователей сообщений.

Стратегия преобразования по умолчанию, используемая JmsTemplate для операций ConvertAndSend() и ReceiveAndConvert() , — это класс SimpleMessageConverter .

SimpleMessageConverter может обрабатывать сообщения TextMessages , BytesMessages , MapMessages и ObjectMessages . Этот класс реализует интерфейс MessageConverter .

Помимо SimpleMessageConverter , Spring JMS предоставляет некоторые другие классы MessageConverter из коробки, такие как MappingJackson2MessageConverter , MarshallingMessageConverter , MessagingMessageConverter .

Более того, мы можем создавать собственные функции преобразования сообщений, просто реализуя методы интерфейса MessageConverter toMessage() и FromMessage() .

Давайте посмотрим пример кода реализации пользовательского MessageConverter ,

public class SampleMessageConverter implements MessageConverter {
public Object fromMessage(Message message)
throws JMSException, MessageConversionException {
//...
}

public Message toMessage(Object object, Session session)
throws JMSException, MessageConversionException {
//...
}
}

7. Пример Spring JMS

В этом разделе мы увидим, как использовать JmsTemplate для отправки и получения сообщений.

Метод по умолчанию для отправки сообщения — JmsTemplate.send() . Он имеет два ключевых параметра, из которых первый параметр — это место назначения JMS, а второй параметр — реализация MessageCreator. JmsTemplate использует метод обратного вызова createMessage() класса MessageCreator для создания сообщения.

JmsTemplate.send() хорош для отправки простых текстовых сообщений, но для отправки пользовательских сообщений JmsTemplate имеет другой метод, называемый c onvertAndSend() .

Ниже мы можем увидеть реализацию этих методов:

public class SampleJmsMessageSender {

private JmsTemplate jmsTemplate;
private Queue queue;

// setters for jmsTemplate & queue

public void simpleSend() {
jmsTemplate.send(queue, s -> s.createTextMessage("hello queue world"));
}
public void sendMessage(Employee employee) { 
System.out.println("Jms Message Sender : " + employee);
Map<String, Object> map = new HashMap<>();
map.put("name", employee.getName()); map.put("age", employee.getAge());
jmsTemplate.convertAndSend(map);
}
}

Ниже приведен класс получателя сообщений, мы называем его POJO, управляемым сообщениями (MDP). Мы видим, что класс SampleListener реализует интерфейс MessageListener и предоставляет текстовую реализацию для метода интерфейса onMessage().

Помимо метода onMessage() , наш класс SampleListener также вызывает метод receiveAndConvert() для получения пользовательских сообщений:

public class SampleListener implements MessageListener {

public JmsTemplate getJmsTemplate() {
return getJmsTemplate();
}

public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
String msg = ((TextMessage) message).getText();
System.out.println("Message has been consumed : " + msg);
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
} else {
throw new IllegalArgumentException("Message Error");
}
}

public Employee receiveMessage() throws JMSException {
Map map = (Map) getJmsTemplate().receiveAndConvert();
return new Employee((String) map.get("name"), (Integer) map.get("age"));
}
}

Мы увидели, как реализовать MessageListener, и ниже мы видим конфигурацию в контексте приложения Spring:

<bean id="messageListener" class="com.foreach.spring.jms.SampleListener" /> 

<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destinationName" ref="IN_QUEUE"/>
<property name="messageListener" ref="messageListener" />
</bean>

DefaultMessageListenerContainer — это контейнер прослушивателя сообщений по умолчанию, который Spring предоставляет вместе со многими другими специализированными контейнерами.

8. Базовая конфигурация с аннотациями Java

@JmsListener единственная аннотация, необходимая для преобразования метода обычного компонента в конечную точку прослушивателя JMS. Spring JMS предоставляет гораздо больше аннотаций для упрощения реализации JMS.

Мы можем увидеть некоторые из примеров классов, аннотированных ниже:

@JmsListener(destination = "myDestination")
public void SampleJmsListenerMethod(Message<Order> order) { ... }

Чтобы добавить несколько слушателей к одному методу, нам просто нужно добавить несколько аннотаций @JmsListener .

Нам нужно добавить аннотацию @EnableJms в один из наших классов конфигурации для поддержки аннотированных методов @JmsListener :

@Configuration
@EnableJms
public class AppConfig {

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory
= new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
return factory;
}
}

9. Обработчик ошибок

Мы также можем настроить собственный обработчик ошибок для нашего контейнера прослушивателя сообщений.

Давайте сначала реализуем интерфейс org.springframework.util.ErrorHandler :

@Service
public class SampleJmsErrorHandler implements ErrorHandler {

// ... logger

@Override
public void handleError(Throwable t) {
LOG.warn("In default jms error handler...");
LOG.error("Error Message : {}", t.getMessage());
}

}

Обратите внимание, что мы переопределили метод handleError() , который просто регистрирует сообщение об ошибке.

Затем нам нужно сослаться на нашу службу обработчика ошибок в DefaultJmsListenerConnectionFactory, используя метод setErrorHandler() :

@Bean
public DefaultJmsListenerContainerFactorybjmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory
= new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setErrorHandler(sampleJmsErrorHandler);
return factory;
}

При этом наш настроенный обработчик ошибок теперь будет ловить любые необработанные исключения и регистрировать сообщение.

При желании мы также можем настроить обработчик ошибок, используя старые конфигурации XML, обновив наш appContext.xml:

<bean id="sampleJmsErrorHandler"
class="com.foreach.spring.jms.SampleJmsErrorHandler" />

<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationName" value="IN_QUEUE" />
<property name="messageListener" ref="messageListener" />
<property name="errorHandler" ref="sampleJmsErrorHandler" />
</bean>

10. Заключение

В этом руководстве мы обсудили конфигурацию и основные понятия Spring JMS. Мы также кратко рассмотрели специфичные для Spring классы JmsTemplate , которые используются для отправки и получения сообщений.

Вы можете найти реализацию кода в проекте GitHub .