Статьи

Веб-розетки с пружиной 4

Я добавляю всю кухонную раковину в небольшое веб-приложение, которое я разрабатываю в рамках этого поста — Spring Boot, Spring Integration, RabbitMQ и, наконец, тему поста, поддержку Websocket в Spring MVC с Spring 4.

Приложение для составления списка землетрясений в режиме реального времени

Окончательное приложение будет перечислять случаи землетрясений по всему миру и будет обновляться в режиме реального времени (если минута может считаться достаточной в реальном времени), по следующим направлениям:

Снимок экрана 2014-03-08 в 12.13.08

Хранение информации о землетрясении

Первая часть приложения каждую минуту опрашивает данные из программы USGS Earthquake опасность, и хранит их. Я решил сохранить его непосредственно в теме RabbitMQ , которая позже будет использоваться для интеграции Websockets. Spring Integration отлично подходит для требований такой функции — используя только конфигурацию, я могу опросить службу USGS, предоставив json-канал этой информации, и записать ее в тему RabbitMQ. Вот как выглядит этот поток:

quakepolling

и исходный полный поток интеграции Spring для того же самого является следующим, единственный код, пропущенный здесь, является конфигурацией для rabbitmq, который является частью другого файла конфигурации:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<import resource="rabbit-context.xml"/>
 <int:inbound-channel-adapter channel="quakeinfotrigger" expression="''">
  <int:poller fixed-delay="60000"></int:poller>
 </int:inbound-channel-adapter>
 
 <int:channel id="quakeinfo"/>
 
 <int:channel id="quakeinfotrigger"></int:channel>
 
 <int-http:outbound-gateway id="quakerHttpGateway"
     request-channel="quakeinfotrigger"
     http-method="GET"
     expected-response-type="java.lang.String"
     charset="UTF-8"
     reply-channel="quakeinfo">
 </int-http:outbound-gateway>
 
 <int-amqp:outbound-channel-adapter amqp-template="amqpTemplate" channel="quakeinfo" />

Итак, теперь у меня есть поток, который собирает информацию о землетрясении и сохраняет ее в теме RabbitMQ под названием «amq.topic» и внутренне подключает ключ маршрутизации «quakes.all» к каждому информационному сообщению о землетрясении, следующий шаг это выяснить, как динамически отображать эту информацию в приложении браузера.

Представление информации о Quake

Spring Framework 4.0+ упрощает разработку веб-части приложения с поддержкой обмена сообщениями на основе Websocket, которая теперь встроена в среду. Spring 4.0 использует STOMP в качестве протокола более высокого уровня для необработанных веб-сокетов — я включил ссылки, которые обеспечивают гораздо большую ясность в деталях поддержки веб-сокетов.

По сути, Spring будет выступать в качестве посредника для браузера, чтобы подписаться на тему землетрясений RabbitMQ и отображать информацию в реальном времени по мере поступления новой информации о землетрясениях, эта схема из ссылок хорошо подводит итог:

Полнофункциональный-Message-Broker

Для поддержки Spring 4 Websockets с внешним брокером требуется, чтобы брокер поддерживал протокол STOMP, что легко сделать с помощью RabbitMQ . С поддержкой STOMP в RabbitMQ конфигурация Spring MVC выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
 
 @Override
 public void configureMessageBroker(MessageBrokerRegistry config) {
  config.enableStompBrokerRelay("/topic/");
  config.setApplicationDestinationPrefixes("/app");
 }
 
 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
  registry.addEndpoint("/quakesep").withSockJS();
 }
}
  • «/ Topic» регистрируется в качестве конечной точки, где Spring выступает в качестве шлюза для поддержки RabbitMQ STOMP
  • «/ App» — это префикс приложения, в котором Spring MVC будет прослушивать запросы браузера, закодированные в фрейме сообщения STOMP, в данном конкретном случае я не получаю никаких запросов от пользовательского интерфейса, поэтому эта конечная точка на самом деле не используется
  • «/ Quakesep» является конечной точкой websocket

Это все, что требуется на стороне сервера!

Теперь, чтобы клиент подписался на сообщение в теме RabbitMQ, я реализовал его в соответствии с примером в одной из справочных статей. В примере используется клиент sockjs , библиотека javascript для эмуляции websocket в браузерах.

Вот как выглядит код JavaScript для подключения к конечной точке websocket «/ quakesep» и подписки на конечную точку «/topic/quakes.all». Это внутренне регистрирует временную очередь в RabbitMQ для этого сеанса веб-сокета и отображает ключ маршрутизации AMQP «quakes.all» в эту временную очередь, по сути отправляя все сообщения о землетрясениях во временную очередь для сеанса.

01
02
03
04
05
06
07
08
09
10
function connect() {
      var socket = new SockJS('/quakesep');
      stompClient = Stomp.over(socket);
      stompClient.connect({}, function(frame) {
          console.log('Connected: ' + frame);
          stompClient.subscribe('/topic/quakes.all', function(message){
              showQuakeInfo(message.body);
          });
      });
  }

вышеприведенная функция showQuakeInfo просто отображает свежую информацию о землетрясениях, когда она доступна из RabbitMQ.

springwebsockets

Весь пример был собран вместе с Spring Boot , это обеспечило сохранение минимальных зависимостей, объявленных в pom-файле, количество настроек для запуска приложения на удивление мало — по сути, код WebSocketConfig, который я отображал выше!

Ресурсы

  1. Архитектура веб-сокетов в Spring Framework
  2. Вебинар по созданию приложений на основе Websocket с использованием Spring Framework

Ссылка: Websockets с Spring 4 от нашего партнера JCG Биджу Кунджуммен в блоге all and sundry.