1. Обзор
В предыдущей статье мы видели, как Spring Remoting можно использовать для предоставления RPC поверх асинхронного канала в качестве очереди AMQP . Однако мы также можем получить тот же результат, используя JMS .
В этой статье мы рассмотрим, как настроить удаленный вызов с помощью Spring Remoting JMS и Apache ActiveMQ в качестве промежуточного программного обеспечения для обмена сообщениями.
2. Запуск брокера Apache ActiveMQ
Apache ActiveMQ – это брокер сообщений с открытым исходным кодом, который позволяет приложениям асинхронно обмениваться информацией и полностью совместим со службой сообщений Java API .
Чтобы запустить наш эксперимент, нам сначала нужно настроить запущенный экземпляр 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 starter, как описано здесь :
org.springframework.boot spring-boot-starter-activemq org.springframework.boot spring-boot-starter-tomcat
Мы явно исключили spring-boot-starter-tomcat , чтобы не иметь Tomcat связанных .jar файлов в пути к классу.
Это, в свою очередь, предотвратит механизм автоматической настройки Spring Boot для запуска встроенного веб-сервера при запуске приложения, поскольку он нам не нужен.
4. Серверное приложение
4.1. Предоставление Услуг
Мы настроим серверное приложение, которое предоставляет услугу Бронирования такси , которую клиенты смогут вызывать.
Первым шагом является объявление компонента, реализующего интерфейс службы, которую мы хотим предоставить клиентам. Это компонент, который будет выполнять бизнес-логику на сервере:
@Bean CabBookingService bookingService() { return new CabBookingServiceImpl(); }
Затем давайте определим очередь, из которой сервер будет извлекать вызовы, указав ее имя в конструкторе:
@Bean Queue queue() { return new ActiveMQQueue("remotingQueue"); }
Как мы уже знаем из предыдущих статей, одной из основных концепций Spring Remoting является Экспортер услуг , компонент , который собирает запросы на вызов из некоторого источника , в данном случае ApacheMQ queue, и вызывает нужный метод реализации службы.
Для работы с JMS мы определяем JmsInvokerServiceExporter :
@Bean JmsInvokerServiceExporter exporter(CabBookingService implementation) { JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter(); exporter.setServiceInterface(CabBookingService.class); exporter.setService(implementation); return exporter; }
Наконец, нам нужно определить слушателя, который несет ответственность за потребление сообщений. Слушатель действует как мост между Apache MQ и 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.baeldung.api
Параметр spring.activemq.broker-url является ссылкой на порт AMQ . Вместо этого требуется более глубокое объяснение параметра spring.activemq.packages.trusted|/. Начиная с версии 5.12.2 ActiveMQ по умолчанию отказывается от любого сообщения типа
Начиная с версии 5.12.2 ActiveMQ по умолчанию отклоняет любое сообщение типа Сообщение об объекте , используется для обмена сериализованными Ява объект, потому что в некоторых контекстах он считается потенциальным вектором атаки на безопасность.
Во всяком случае, можно указать AMQ принимать сериализованные объекты в указанных пакетах. org.springframework.remoting.support – это пакет, содержащий основные сообщения, представляющие вызов удаленного метода и его результат. Посылка
Пакет com.baeldung.api содержит параметры и результаты нашего сервиса. java.lang добавляется потому , что объект, представляющий результат бронирования такси, ссылается на строку |, поэтому нам также нужно сериализовать ее.
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 . Итак, давайте сначала запустим Apache MQ , затем серверное приложение и, наконец, клиентское приложение, которое вызовет удаленную службу.
6. Заключение
В этом кратком руководстве мы увидели, как мы могли бы использовать Spring Remoting для предоставления RPC поверх системы JMS в качестве AMQ .
Spring Remoting продолжает демонстрировать, как легко быстро настроить асинхронный вызов независимо от базового канала.
Как обычно, вы найдете источники на GitHub .