2014-10-16 18 views
9

Tôi đã duyệt rất nhiều ví dụ về Web Socket, các trang trình bày và chúng chủ yếu tập trung vào một kịch bản khá đơn giản trong đó giao tiếp client-server được khởi tạo bởi ứng dụng khách.Làm cách nào để triển khai push to client bằng cách sử dụng Java WebSockets?

Tôi quan tâm đến một tình huống khác, điều này có vẻ không kém phần thực tế: máy chủ thuần đẩy cho khách hàng.

Ví dụ tôi lưu ý là một ứng dụng cập nhật giá trị cổ phiếu trên trang web. Hãy tưởng tượng có một hệ thống trao đổi cổ phiếu hệ thống bên ngoài, đó là gửi một thông điệp JMS cho mỗi thay đổi giá trị cổ phiếu đã đăng ký.

Tôi muốn biết cách dịch sự kiện JMS đến như vậy thành một sự thúc đẩy máy chủ và cho nó một cách hiệu quả và thành ngữ từ một quan điểm của Java EE 7.

Theo như tôi có thể hiểu được spec, nên anh phải viết một endpoint ổ cắm 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()); 
    } 
} 

Mọi thứ đều dễ dàng khi tôi nhận được một tin nhắn từ lối vào, tôi có thể làm bất cứ điều gì tôi thích ở @OnMessage. Nhưng trong ví dụ của tôi, tôi sẽ không nhận được bất kỳ tin nhắn nào từ phía khách hàng, tôi sẽ nhận được một sự kiện từ một số hệ thống bên ngoài.

Có một vài cách tiếp cận. Ví dụ: tôi có thể tạo một chuỗi trong phương thức @OnOpen, như được minh họa trong this blog. Trong thực tế rằng cách tiếp cận có thể cho thấy một thiếu sót vì mỗi khách hàng tôi sẽ cần phải tạo ra một chủ đề sống mới, có khả năng dài.

Người ta có thể làm tốt hơn bằng cách sử dụng kênh NIO với bộ chọn, nhưng điều này sẽ yêu cầu một số loại quản lý kênh "làm bằng tay". Doable, nhưng khá cồng kềnh.

Một giải pháp khác là ping một số hệ thống khác để cập nhật, nhưng một lần nữa nó sẽ là loại xấu xí. Ngoài ra tôi cũng không chắc chắn nếu một phương pháp @OnOpen có nghĩa là để được sử dụng theo cách đó.

Lý tưởng nhất là một thông báo JMS đến sẽ kích hoạt một Web Socket đẩy tới máy khách. Bất kỳ ý tưởng làm thế nào để thực hiện một cái gì đó như thế này độc đáo?

+1

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

+0

Cảm ơn bạn đã liên kết. Điều đó có vẻ khá tốt (ở điểm 7 có thực tế đẩy thực hiện). Nó được thực hiện theo cách sau: chúng ta phải tạo một tập hợp tất cả các phiên (bộ đồng bộ tĩnh). Sau đó, nếu chúng ta muốn gửi push đến client, chúng ta sẽ đi qua tập hợp đó và kích hoạt push. Có một vài nhược điểm của cách tiếp cận đó, nhưng không có gì không thể vượt qua được. –

+0

Câu hỏi của chúng tôi liên quan chặt chẽ: https://stackoverflow.com/questions/27037570/find-websocket-session-by-id-in-java-ee-7/27045235 – Ihromant

Trả lời

4

Có lẽ đây không phải là cách thanh lịch nhất mà chỉ để chứng minh ý tưởng. Phương thức phát sóng() sẽ gửi tin nhắn tới tất cả các khách hàng được kết nối.

@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

có tốt hơn không khi sử dụng phương thức getAsyncRemote() hoặc getBasicRemote()? –

1

tôi làm điều đó theo cách này (không yêu cầu khách hàng là cần thiết):

@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()); 
    } 
    } 
} 
Các vấn đề liên quan