2014-10-16 13 views
9

Ich habe viele Web-Socket-Beispiele und Präsentationsfolien durchsucht und sie konzentrieren sich hauptsächlich auf eine eher einfache Szenarien, in denen Client-Server-Kommunikation vom Client initiiert wird.Wie implementiert Push to Client mit Java EE 7 WebSockets?

Ich interessiere mich für ein anderes Szenario, das gleichermaßen praktisch zu sein scheint: pure Server Push to Client.

Beispiel Ich habe im Sinn eine Anwendung, die Aktienwerte auf einer Website aktualisiert. Stellen Sie sich vor, es gibt ein externes Systembörsensystem, das für jede Änderung des gezeichneten Bestands eine JMS-Nachricht sendet.

Ich würde gerne wissen, wie man solche eingehende JMS-Ereignis in einen Server-Push und es effizient und idiomatisch aus einer Java EE 7 Sicht zu übersetzen.

Soweit ich die Spezifikation verstehen kann, soll ich einen Web-Socket-Endpunkt

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

Alles ist schreiben einfach, wenn ich eine Nachricht vom Frontend bekommen, kann ich tun, was ich in der gerne @OnMessage Methode. Aber in meinem Beispiel bekomme ich keine Nachricht vom Client, ich bekomme ein Event von einem externen System.

Es gibt ein paar Ansätze. Zum Beispiel kann ich einen Thread in einer @OnOpen Methode erstellen, wie in this blog demonstriert. In der Praxis könnte dieser Ansatz einen Mangel aufweisen, da ich für jeden Kunden einen neuen, potenziell langlebigen Thread erstellen müsste.

Man kann besser NIO-Kanäle mit Selektoren verwenden, aber dies würde eine Art "handgemachte" Kanalverwaltung erfordern. Machbar, aber eher umständlich.

Eine andere Lösung wäre ein anderes System für Updates zu pingen, aber wieder wäre es irgendwie hässlich. Außerdem bin ich mir auch nicht sicher, ob eine @OnOpen Methode so verwendet werden soll.

Im Idealfall würde eine eingehende JMS-Nachricht einen Web-Socket-Push an den Client auslösen. Irgendwelche Ideen wie man sowas nett umsetzen kann?

+1

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

+0

Danke für den Link. Das sieht ziemlich gut aus (in Punkt 7 gibt es eine tatsächliche Push-Implementierung). Dies geschieht folgendermaßen: Wir müssen eine Menge aller Sitzungen erstellen (statische synchronisierte Menge). Wenn wir dann Push an den Client senden wollen, gehen wir durch diesen Satz und stoßen Pushs aus. Es gibt ein paar Nachteile dieses Ansatzes, aber nichts, was nicht überwunden werden kann. –

+0

Unsere Frage ist stark verwandt: https://stackoverflow.com/questions/27037570/find-websocket-session-by-id-in-java-ee-7/27045235 – Ihromant

Antwort

4

Wahrscheinlich ist dies nicht der eleganteste Weg, sondern nur um die Idee zu demonstrieren. Methode broadcast() wird Nachricht an alle verbundenen Clients senden.

@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

ist es besser, getAsyncRemote() oder getBasicRemote() -Methode zu verwenden? –

1

ich es auf diese Weise (keine Client-Anforderung ist erforderlich):

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