2014-10-16 91 views
9

我浏览过很多Web Socket示例,演示文稿幻灯片,它们大多集中在客户端发起客户端 - 服务器通信的相当简单的场景中。如何使用Java EE 7 WebSocket实现推送到客户端?

我对另一种场景感兴趣,它似乎同样实用:纯服务器推送到客户端。

示例我记住的是一个应用程序,它可以更新网站上的股票价值。假设有一个外部系统证券交易所系统,它为每个订阅的股票价值变化发送JMS消息。

我想知道如何将这种传入的JMS事件转换为服务器推送,并从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套接字推送到客户端。任何想法如何很好地实现这样的东西?

+1

https://blogs.oracle.com/brunoborges/entry/integrating_websockets_and_jms_with – 2014-10-17 07:48:24

+0

感谢您的链接。这看起来相当不错(第7点有实际的推送实施)。这是通过以下方式完成的:我们必须创建一组所有会话(静态同步集)。然后,如果我们想发送推送给客户端,我们会通过该设置并触发推送。这种方法有一些缺点,但没有什么是无法克服的。 – 2014-10-17 08:14:23

+0

我们的问题是强烈关联的:https://stackoverflow.com/questions/27037570/find-websocket-session-by-id-in-java-ee-7/27045235 – Ihromant 2014-11-21 18:09:10

回答

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()方法更好吗? – 2017-05-02 21:27:23

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()); 
    } 
    } 
} 
相关问题