1. Обзор
В предыдущей статье мы видели, как можно использовать Spring Remoting для предоставления
RPC
поверх асинхронного канала в виде очереди AMQP .
Однако мы можем получить тот же результат и с помощью JMS
.
В этой статье мы фактически рассмотрим, как настроить удаленный вызов с использованием Spring Remoting JMS
и Apache ActiveMQ
в качестве промежуточного программного обеспечения для обмена сообщениями.
2. Запуск брокера Apache ActiveMQ
Apache ActiveMQ
— это брокер сообщений с открытым исходным кодом , который позволяет приложениям обмениваться информацией асинхронно и полностью совместим с API
службы сообщений Java
. ``
Чтобы запустить наш эксперимент, нам сначала нужно настроить работающий экземпляр ActiveMQ
. Мы можем выбрать один из нескольких способов: выполнить шаги, описанные в официальном руководстве , встроить его в приложение Java
или, проще говоря, запустить контейнер Docker с помощью следующей команды:
docker run -p 61616:61616 -p 8161:8161 rmohr/activemq:5.14.3
Это запустит контейнер ActiveMQ
, который предоставляет через порт 8081 простой административный веб-интерфейс, через который мы можем проверить доступные очереди, подключенных клиентов и другую административную информацию. Вместо этого клиентам JMS
потребуется использовать порт 61616 для подключения к брокеру и обмена сообщениями.
3. Зависимости Maven
Как и в предыдущих статьях, посвященных Spring Remoting
, мы собираемся настроить сервер и клиентское приложение Spring Boot
, чтобы показать, как работает JMS Remoting
.
Как обычно, мы тщательно выбираем стартовые зависимости Spring Boot ,
как описано здесь :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
Мы явно исключили spring-boot-starter-tomcat
, чтобы не иметь файлов .jar
, связанных с Tomcat
, в пути к классам. ``
Это, в свою очередь, не позволит механизму автоконфигурации Spring Boot
запускать встроенный веб-сервер при запуске приложения, поскольку он нам не нужен.
4. Серверное приложение
4.1. Разоблачить сервис
Мы настроим серверное приложение, предоставляющее службу CabBookingService
, которую смогут вызывать клиенты.
Первый шаг — объявить bean-компонент, реализующий интерфейс службы, которую мы хотим предоставить клиентам. Это bean-компонент, который будет выполнять бизнес-логику на сервере:
@Bean
CabBookingService bookingService() {
return new CabBookingServiceImpl();
}
Затем определим очередь, из которой сервер будет получать вызовы, указав ее имя в конструкторе:
@Bean
Queue queue() {
return new ActiveMQQueue("remotingQueue");
}
Как мы уже знаем из предыдущих статей, одной из основных концепций Spring Remoting
является Service Exporter
, компонент, который собирает запросы на вызов из какого-то источника , в данном случае очереди ApacheMQ
─ и вызывает нужный метод на реализации сервиса .
Для работы с JMS
мы определяем JmsInvokerServiceExporter
:
@Bean
JmsInvokerServiceExporter exporter(CabBookingService implementation) {
JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter();
exporter.setServiceInterface(CabBookingService.class);
exporter.setService(implementation);
return exporter;
}
Наконец, нам нужно определить слушателя, который отвечает за потребление сообщений. Прослушиватель действует как мост между ApacheMQ
и JmsInvokerServiceExporter ,
он прослушивает сообщения вызова, доступные в очереди, перенаправляет вызов экспортеру службы и сериализует обратно результаты:
@Bean SimpleMessageListenerContainer listener(
ConnectionFactory factory,
JmsInvokerServiceExporter exporter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(factory);
container.setDestinationName("remotingQueue");
container.setConcurrentConsumers(1);
container.setMessageListener(exporter);
return container;
}
4.2. Конфигурация
Давайте не забудем настроить файл application.properties
, чтобы позволить Spring Boot
настраивать некоторые основные объекты, например ConnectionFactory
, необходимые слушателю. Значения различных параметров в основном зависят от способа
Значения различных параметров в основном зависят от того, как был установлен ApacheMQ
, и следующая конфигурация является разумной конфигурацией для нашего контейнера Docker
, работающего на той же машине, на которой мы будем запускать эти примеры:
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.packages.trusted=org.springframework.remoting.support,java.lang,com.foreach.api
Параметр spring.activemq.broker-url
является ссылкой на порт AMQ .
Вместо этого требуется более глубокое объяснение параметра spring.activemq.packages.trusted
. Начиная с версии 5.12.2 ActiveMQ по умолчанию отклоняет любое сообщение типа
Начиная с версии 5.12.2 ActiveMQ по умолчанию отклоняет любое сообщение типа ObjectMessage
, используемое для обмена сериализованным объектом Java
, поскольку в некоторых контекстах оно считается потенциальным вектором для атаки на систему безопасности.
В любом случае можно указать AMQ
принимать сериализованные объекты в указанных пакетах. org.springframework.remoting.support
— это пакет, содержащий основные сообщения, представляющие собой вызов удаленного метода и его результат. Посылка
Пакет com.foreach.api
содержит параметры и результаты нашего сервиса. java.lang
добавлен, потому что объект, который представляет результат заказа такси, ссылается на String
, поэтому нам также нужно сериализовать его.
5. Клиентское приложение
5.1. Вызвать удаленную службу
Теперь займемся клиентом. Опять же, нам нужно определить очередь, в которую будут записываться сообщения вызова. Нам нужно перепроверить, что и клиент, и сервер используют одно и то же имя.
@Bean
Queue queue() {
return new ActiveMQQueue("remotingQueue");
}
Затем нам нужно настроить экспортер:
@Bean
FactoryBean invoker(ConnectionFactory factory, Queue queue) {
JmsInvokerProxyFactoryBean factoryBean = new JmsInvokerProxyFactoryBean();
factoryBean.setConnectionFactory(factory);
factoryBean.setServiceInterface(CabBookingService.class);
factoryBean.setQueue(queue);
return factoryBean;
}
Теперь мы можем использовать удаленную службу, как если бы она была объявлена как локальный компонент:
CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));
5.2. Запустите пример
Также для клиентского приложения мы должны правильно выбрать значения в файле .properties приложения.
В обычной настройке они будут точно соответствовать тем, которые используются на стороне сервера.
Этого должно быть достаточно, чтобы продемонстрировать удаленный вызов через Apache AMQ
. Итак, давайте сначала запустим ApacheMQ
, затем серверное приложение и, наконец, клиентское приложение, которое будет вызывать удаленную службу.
6. Заключение
В этом кратком руководстве мы увидели, как можно использовать Spring Remoting
для предоставления RPC
поверх системы JMS
в виде AMQ
.
Spring Remoting продолжает демонстрировать, как легко и быстро настроить асинхронный вызов независимо от основного канала.
Как обычно, вы найдете исходники на GitHub .