如何获取现有的 websocket 实例 [英] How to get an existing websocket instance

查看:36
本文介绍了如何获取现有的 websocket 实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,该应用程序使用 Websockets (Java EE 7) 向所有连接的客户端异步发送消息.每当创建新文章(我的应用中的参与模式)时,服务器(Websocket 端点)都应发送这些消息.

I'm working on an application that uses Websockets (Java EE 7) to send messages to all the connected clients asynchronously. The server (Websocket endpoint) should send these messages whenever a new article (an engagement modal in my app) is created.

每次与 websocket 端点建立连接时,我都会将相应的会话添加到一个列表中,我可以在外部访问该列表.

Everytime a connection is established to the websocket endpoint, I'm adding the corresponding session to a list, which I could be able to access outside.

但我遇到的问题是,当我访问这个创建的 websocket 端点时,所有客户端都从外部(任何其他业务类)连接到该端点,我得到了现有实例(如单例).

But the problem I had is, when I'm accessing this created websocket endpoint to which all the clients connected from outside (any other business class), I've get the existing instance (like a singleton).

那么,请您给我建议一种方法,我可以获得 websocket 端点的现有实例,因为我无法将它创建为 new MyWebsocketEndPoint() 因为它会在每次请求来自 websocket 的内部机制时创建收到一个客户.

So, can you please suggest me a way I can get an existing instance of the websocket endpoint, as I can't create it as new MyWebsocketEndPoint() coz it'll be created by the websocket internal mechanism whenever the request from a client is received.

参考:

private static WebSocketEndPoint INSTANCE = null;

public static WebSocketEndPoint getInstance() {
if(INSTANCE == null) {
// Instead of creating a new instance, I need an existing one
    INSTANCE = new WebSocketEndPoint ();
}
        return INSTANCE;
}

提前致谢.

推荐答案

容器为每个客户端连接创建了一个单独的端点实例,所以你不能做你想做的事.但我认为您要做的是在事件发生时向所有活动的客户端连接发送一条消息,这相当简单.

The container creates a separate instance of the endpoint for every client connection, so you can't do what you're trying to do. But I think what you're trying to do is send a message to all the active client connections when an event occurs, which is fairly straightforward.

javax.websocket.Session 类具有 getBasicRemote 方法来检索表示与该会话关联的端点的 RemoteEndpoint.Basic 实例.

The javax.websocket.Session class has the getBasicRemote method to retrieve a RemoteEndpoint.Basic instance that represents the endpoint associated with that session.

您可以通过调用 Session.getOpenSessions() 检索所有打开的会话,然后遍历它们.该循环将向每个客户端连接发送一条消息.这是一个简单的例子:

You can retrieve all the open sessions by calling Session.getOpenSessions(), then iterate through them. The loop will send each client connection a message. Here's a simple example:

@ServerEndpoint("/myendpoint")
public class MyEndpoint {
  @OnMessage
  public void onMessage(Session session, String message) {
    try {  
      for (Session s : session.getOpenSessions()) {
        if (s.isOpen()) {
          s.getBasicRemote().sendText(message);
        }
    } catch (IOException ex) { ... }
  } 
} 

但在您的情况下,您可能希望使用 CDI 事件来触发对所有客户端的更新.在这种情况下,您将创建一个 CDI 事件,您的 Websocket 端点类中的方法会观察到该事件:

But in your case, you probably want to use CDI events to trigger the update to all the clients. In that case, you'd create a CDI event that a method in your Websocket endpoint class observes:

@ServerEndpoint("/myendpoint")
public class MyEndpoint {
  // EJB that fires an event when a new article appears
  @EJB
  ArticleBean articleBean;
  // a collection containing all the sessions
  private static final Set<Session> sessions = 
          Collections.synchronizedSet(new HashSet<Session>());

  @OnOpen
  public void onOpen(final Session session) {
    // add the new session to the set
    sessions.add(session);
    ...
  }

  @OnClose
  public void onClose(final Session session) {
    // remove the session from the set
    sessions.remove(session);
  }

  public void broadcastArticle(@Observes @NewArticleEvent ArticleEvent articleEvent) {
    synchronized(sessions) {
      for (Session s : sessions) {
        if (s.isOpen()) {
          try {
            // send the article summary to all the connected clients
            s.getBasicRemote().sendText("New article up:" + articleEvent.getArticle().getSummary());
          } catch (IOException ex) { ... }
        }
      }
    }
  }
}

上面例子中的 EJB 会做类似的事情:

The EJB in the above example would do something like:

...
@Inject
Event<ArticleEvent> newArticleEvent;

public void publishArticle(Article article) {
  ...
  newArticleEvent.fire(new ArticleEvent(article));
  ...
}

请参阅关于 WebSockets 的 Java EE 7 教程章节和CDI 事件.

See the Java EE 7 Tutorial chapters on WebSockets and CDI Events.

修改了 @Observer 方法以使用事件作为参数.

Modified the @Observer method to use an event as a parameter.

编辑 2:按照 @gcvt 将循环包装在 broadcastArticle 中同步.

Edit 2: wrapped the loop in broadcastArticle in synchronized, per @gcvt.

编辑 3:更新了 Java EE 7 教程的链接.干得好,甲骨文.嘘.

Edit 3: Updated links to Java EE 7 Tutorial. Nice job, Oracle. Sheesh.

这篇关于如何获取现有的 websocket 实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆