如何获取现有的Websocket实例 [英] How to get an existing websocket instance
问题描述
我正在开发一个使用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终结点的现有实例吗,因为我无法将其创建为新的MyWebsocketEndPoint(),因为只要有来自Websocket内部机制的请求,它都将由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.
按照@gcvt,将循环循环同步地包裹在broadcastArticle中.
Edit 2: wrapped the loop in broadcastArticle in synchronized, per @gcvt.
更新了指向Java EE 7教程的链接.干得好,Oracle.嘘.
Edit 3: Updated links to Java EE 7 Tutorial. Nice job, Oracle. Sheesh.
这篇关于如何获取现有的Websocket实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!