2014-10-16 2 views
9

Я просмотрел множество примеров веб-сокетов, презентационных слайдов, и они в основном сосредоточены на довольно простых сценариях, в которых клиент-сервер инициирует общение клиента.Как реализовать push-клиент с помощью Java EE 7 WebSockets?

Меня интересует еще один сценарий, который, как представляется, одинаково практичен: чистый серверный клик.

Пример Я имею в виду приложение, которое обновляет стоимость акций на веб-сайте. Представьте себе, что существует система фондовой системы внешней системы, которая отправляет JMS-сообщение для каждого изменения стоимости подписанных акций.

Я хотел бы знать, как перевести такое входящее JMS-событие в серверный push и эффективно и идиоматически с точки зрения Java EE 7.

Насколько я понимаю, спецификации, я должен написать веб-сокет

@ServerEndpoint("/demo") 
public class WSEndpoint { 
    private static final Logger LOG = Logger.getLogger(WSEndpoint.class); 

    @OnMessage 
    public void onMessage(String message, Session session) { 
    LOG.info("Received : " + message + ", session:" + session.getId()); 
    } 

    @OnOpen 
    public void open(Session session) { 
    LOG.info("Open session:" + session.getId());   
    } 

    @OnClose 
    public void close(Session session, CloseReason c) { 
    log.info("Close session:" + session.getId()); 
    } 
} 

Все легко, когда я получаю сообщение от интерфейса, я могу делать все, что мне нравится в @OnMessage способ. Но в моем примере я не получу никакого сообщения от клиента, я получу событие из какой-то внешней системы.

Существует несколько подходов. Например, я могу создать поток в методе @OnOpen, как показано в this blog. На практике такой подход может показаться недостатком, поскольку для каждого клиента мне понадобится создать новый, потенциально длинный живой поток.

Можно использовать каналы NIO с селекторами, но это потребует какого-то управления каналами «вручную». Возможность, но довольно громоздкая.

Другим решением будет ping какой-либо другой системы для обновлений, но опять же это будет отвратительно. Кроме того, я также не уверен, что метод @OnOpen предназначен для использования таким образом.

В идеальном случае входящее JMS-сообщение будет вызывать нажатие Web Socket клиенту. Любые идеи, как реализовать что-то вроде этого красиво?

+1

https://blogs.oracle.com/brunoborges/entry/integrating_websockets_and_jms_with –

+0

Спасибо за ссылку. Это выглядит неплохо (в пункте 7 есть реальная реализация push). Это делается следующим образом: мы должны создать набор всех сеансов (статический синхронизированный набор). Затем, если мы хотим отправить push клиенту, мы проходим через этот набор и триггерные нажатия. Есть несколько недостатков этого подхода, но ничего, что невозможно преодолеть. –

+0

Наш вопрос сильно связан: https://stackoverflow.com/questions/27037570/find-websocket-session-by-id-in-java-ee-7/27045235 – Ihromant

ответ

4

Возможно, это не самый элегантный способ, но просто для демонстрации идеи. Метод broadcast() отправит сообщение всем подключенным клиентам.

@ServerEndpoint("/echo") 
public class ServerEndPoint { 

    private static Set<Session> userSessions = Collections.newSetFromMap(new ConcurrentHashMap<Session, Boolean>()); 

    @OnOpen 
    public void onOpen(Session userSession) { 
     userSessions.add(userSession); 
    } 

    @OnClose 
    public void onClose(Session userSession) { 
     userSessions.remove(userSession); 
    } 

    @OnMessage 
    public void onMessage(String message, Session userSession) { 
     broadcast(message); 
    } 

    public static void broadcast(String msg) { 
     for (Session session : userSessions) { 
      session.getAsyncRemote().sendText(msg); 
     } 
    } 

} 
+0

лучше использовать метод getAsyncRemote() или getBasicRemote()? –

1

Я делаю это так (запрос клиента не требуется):

@ServerEndpoint("/hello") 
public class HelloWebSocket { 

    @OnOpen 
    public void greetTheClient(Session session){ 
     try { 
     session.getBasicRemote().sendText("Hello stranger"); 

    } catch (IOException ioe) { 
     System.out.println(ioe.getMessage()); 
    } 
    } 
} 
Смежные вопросы