Интеграция Spring, соединяющая входящий HTTP-шлюз с исходящим шлюзом Websocket

Я хочу создать REST-сервис для включения света. Я хочу иметь следующую архитектуру:

  • Множество встроенных систем, каждая из которых подключена к одному световому экземпляру
  • Каждая встроенная система имеет клиент websocket, который подключается к моему серверу.
  • На моем сервере есть служба REST, которая позволяет веб-клиентам выбрать один легкий экземпляр и включить его.
  • Служба REST будет иметь параметр, чтобы указать ссылку для одного экземпляра источника света, подключенного к системе и отправить сообщение клиенту websocket, дождаться сообщения подтверждения от клиента и вернуть ответ REST.

Я хотел бы сделать это с помощью Spring Integration framework. Я думал о чем-то вроде:

Запрос: входящий HTTP GW -> исходящий Websocket GW

Ответ: Входящий HTTP GW ‹- Входящий Websocket GW

Проблема в том, что я не знаю, как указать клиент websocket. Есть идеи, как это сделать?

На данный момент и на основе полученных мной ответов это псевдокод, который предоставляет решение:

<!-- REST service to turn on the light -->    
<int-http:inbound-gateway
        supported-methods="POST"
        request-channel="lightOnRequest"
        reply-channel="lightOnResponse"
        path="rest/lighton/{sessionId}">
    <int-http:header name="{sessionId}" expression="{sessionId}"/>
</int-http:inbound-gateway>

<!-- We add a header SESSION_ID_HEADER to choose the websocket destination client -->
<int:header-enricher 
    input-channel="lightOnRequest" 
    output-channel="lightOnClientRequest">
    <int:header 
        name="#{T(...SimpMessageHeaderAccessor).SESSION_ID_HEADER}"
        expression="headers.sessionId"/>
    <int:header-channels-to-string/>
</int:header-enricher>

<!-- Websocket out to client -->
<int-websocket:outbound-channel-adapter 
    channel="lightOnClientRequest" 
    container="serverWebSocketContainer" />

<!-- Response reception from the Websocket client -->
<int-websocket:inbound-channel-adapter 
    channel="lightOnClientResponse" 
    container="serverWebSocketContainer" />

<!-- The websocket client provides again the reply channel in the headers.
     The bridge connects the response to the reply channel -->
<int:bridge input-channel="lightOnClientResponse"/>

person Omar BELKHODJA    schedule 16.03.2015    source источник


Ответы (1)


К сожалению, ваш вопрос не ясен. Если ваш материал WebSocket основан на адаптерах Spring Integration WEbSocket, у вас есть ServerWebSocketContainer, который имеет getSessions() для возврата Map<String, WebSocketSession> подключенных клиентских сеансов. Следовательно, вы можете открывать доступ конечным пользователям через службу REST.

Когда клиент выбирает один сеанс и отправляет HTTP-запрос, вы можете просто перенаправить это сообщение с SimpMessageHeaderAccessor.SESSION_ID_HEADER на <int-websocket:outbound-channel-adapter>.

И да, вы можете получить подтверждение с помощью <int-websocket:inbound-channel-adapter> и автоматически переслать его в ответ REST. Но для этого вам нужно преобразовать TemporaryReplyChannel из <int-http:inbound-gateway> в String, используя <header-channels-to-string> на <header-enricher>.

Ваше клиентское приложение WebSocket должно гарантировать возврат этих заголовков запросов с replyChannel при отправке подтверждения сеансу. С Spring Integration на этой стороне все должно быть прозрачным.

Сообщите мне, если я что-то пропустил.

ОБНОВЛЕНИЕ

Хороший. Спасибо за дополнительную информацию! Ваша конфигурация выглядит хорошо. Некоторые примечания: 1. Нет необходимости иметь reply-channel="lightOnResponse": входящий HTTP-шлюз очень хорошо ждет ответа от TemporaryReplyChannel. 2. Пожалуйста, добавьте <header-channels-to-string> к вашему <header-enricher> перед пересылкой в ​​WebSocket. 3. <int-websocket:inbound-channel-adapter> может просто отправить свое входящее сообщение простому bridge: <bridge input-channel="lightOnClientResponse">. В этом случае без output-channel он передает сообщение replyChannel из заголовков. Следовательно, ваш шлюз входящей почты HTTP получит соответствующий ответ.

person Artem Bilan    schedule 16.03.2015
comment
Привет, Артем. Спасибо за ваш ответ. Вся моя разработка основана на Spring Integration, что означает, что да, материал Websocket основан на Spring Integration Adapters. Теперь из вашего ответа я понимаю, как выбрать клиент websocket (на основе SESSION_ID_HEADER), и я смогу перенаправить его на правильного клиента. Но я не понимаю, как я могу автоматически переслать ответ websocket как ответ REST. Я пришлю фрагмент кода ниже, надеясь, что вы еще раз прокомментируете. - person Omar BELKHODJA; 16.03.2015