[英]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.