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 .