在JSR-356中广播服务器启动的WebSocket消息的最佳做法是什么?
为了澄清,我知道在使用@OnMessage
注释时回复甚至广播是如何工作的,但我想从服务器发送事件而不首先从客户端接收消息。换句话说,我想我需要在下面的代码中引用MessageServerEndpoint
实例。
我已经看过以下解决方案,但它使用的是静态方法而且不是很优雅。
@ServerEndpoint(value = "/echo")
public class MessageServerEndpoint {
private static Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());
@OnOpen
public void onOpen(Session session) {
sessions.add(session);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
sessions.remove(session);
}
// Static method - I don't like this at all
public static void broadcast(String message) {
for (Session session : sessions) {
if (session.isOpen()) {
session.getBasicRemote().sendText(message);
}
}
}
}
public class OtherClass {
void sendEvent() {
MessageServerEndpoint.broadcast("test");
// How do I get a reference to the MessageServerEndpoint instance here instead?
}
}
答案 0 :(得分:0)
我通过扩展ServerEndpointConfig.Configurator
并覆盖getEndpointInstance()
来解决问题,我可以保存端点实例:
public class MyEndpointConfigurator extends ServerEndpointConfig.Configurator
private Set<MyEndpoint> endpoints = Collections.synchronizedSet(new HashSet<>());
@Override
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
try {
T endpoint = endpointClass.newInstance();
MyEndpoint myEndpoint = (MyEndpoint) endpoint;
myEndpoint.setConfigurator(this);
endpoints.add(myEndpoint);
return endpoint;
} catch (IllegalAccessException e) {
throw new InstantiationException(e.getMessage());
}
}
// Call this from MyEndpoint.onClose()
public void removeInstance(MyEndpoint endpoint) {
endpoints.remove(endpoint);
}
}
由于我有MyEndpointConfigurator
的引用,我也有对所有端点的引用。
它仍然感觉像是一个黑客,但似乎可以做到这一点。