簡體   English   中英

如何使用Java EE 7 WebSockets實現對客戶端的推送?

[英]How to implement push to client using Java EE 7 WebSockets?

我瀏覽了很多Web Socket示例,演示幻燈片,它們主要集中在客戶端發起客戶端 - 服務器通信的相當簡單的場景中。

我對另一個場景感興趣,這似乎同樣實用:純服務器推送到客戶端。

示例我想到的是一個更新網站上股票價值的應用程序。 想象一下,有一個外部系統股票交易系統,它為每個訂閱的股票價值變化發送JMS消息。

我想知道如何將這樣的傳入JMS事件轉換為服務器推送,並從Java EE 7的角度高效地和慣用地轉換它。

據我所知,我應該編寫一個Web套接字端點

@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方法中做任何我喜歡的@OnMessage 但在我的例子中,我不會從客戶端收到任何消息,我會從某個外部系統獲得一個事件。

有幾種方法。 例如,我可以在@OnOpen方法中創建一個線程,如本博客所示 實際上,這種方法可能會顯示出一個缺點,因為對於每個客戶端,我都需要創建一個新的,可能很長的生命線程。

使用選擇器的NIO通道可以做得更好,但這需要某種“手工制作”的通道管理。 可行,但相當繁瑣。

另一個解決方案是ping其他系統進行更新,但同樣會有點難看。 另外我也不確定是否以這種方式使用@OnOpen方法。

理想情況下,傳入的JMS消息將觸發Web Socket推送到客戶端。 任何想法如何很好地實現這樣的事情?

可能這不是最優雅的方式,只是為了展示想法。 方法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);
        }
    }

}

我是這樣做的(不需要客戶端請求):

@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());
    }
   }
}

將活動sessionList存儲在另一個SessionManager類中。

List<Session> socketSessions = new ArrayList<>();

@OnOpen傳入會話添加到列表中。 @OnClose列表中刪除會話

@OnClose
public void close(Session session) {
  sessionManager.removeSession(session);
}

要向所有人發送消息,

public void broadcast(String message){
    for(Session session: sessionList){
        session.getBasicRemote().sendText(message);
    }
}

您可以在事件觸發的任何位置使用sessionManager.broadcast()方法。

這是一個完整的例子,說明如何使用websocket來推動HTML5 websocket API。 https://metamug.com/article/java-push-notification-with-websocket.php

我使用omnifaces套接字組件實現了類似於您的問題的解決方案。 通知由JMS消息觸發,收件人可以是特定用戶或所有用戶。 博客文章網址https://konstpan.wordpress.com/2018/03/25/push-notifications-in-a-jee-web-application-secured-by-keycloak/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM