有没有办法处理每个会话的websocket的服务器端关闭事件?这就是我目前的实现方式:
@ServerEndpoint("/ws")
public class WebsocketServerEndpoint {
@OnOpen
public void onOpen(Session session) {
System.out.println("Websocket opened");
CustomWebsocketHandler handler = new CustomWebsocketHandler(session); // see below
// ...
}
@OnClose
public void onClose(Session session, CloseReason reason) {
System.out.println("Websocket closed. Reason: " + reason);
}
}
但我想在自定义对象中包装新的Session
实例。对于消息,我可以通过addMessageHandler
将处理程序直接添加到特定会话。但是如何在该特定会话中为onClose
事件添加处理程序?:
class CustomWebsocketHandler {
public CustomWebsocketHandler(Session session) {
session.addMessageHandler((MessageHandler.Whole<String>) this::handleMessage);
// How to hook up close event to handleClose()?
}
private void handleMessage(String message) { /* ... */ }
private void handleClose() { /* ... */ }
}
我的一个想法是跟踪WebsocketServerEndpoint
及其各自的CustomWebsocketHandler
实例中的每个会话,并针对每个关闭事件检查它们,转发事件。然而,这非常麻烦并且容易出错:
@ServerEndpoint("/ws")
public class WebsocketServerEndpoint {
private List<Pair<Session, CustomWebsocketHandler>> sessions = new ArrayList<>();
@OnOpen
public void onOpen(Session session) {
// ...
sessions.add(Pair.of(session, handler)); // not hashable I suppose
}
@OnClose
public void onClose(Session session, CloseReason reason) {
// ...
for (Iterator<Pair<Session, CustomWebsocketHandler>> it = sessions.iterator(); it.hasNext(); ) {
Pair<Session, CustomWebsocketHandler> pair = it.next();
if (pair.getLeft() == session) {
pair.getRight().handleClose();
it.remove();
break;
}
}
}
}
在客户端这很容易,因为每个连接都可以使用自己的ClientEndpoint
实例 - 带注释的类:
webSocketContainer.connectToServer(endpointInstance, websocketURI);
服务器端是否存在类似的情况,或者是否可以完全处理每个会话的服务器端onClose
(最终还是onError
)事件?
答案 0 :(得分:0)
默认情况下,为每个新客户端创建ServerEndpoint
- 带注释的类的新实例。此行为由ServerEndpointConfig.Configurator#getEndpointInstance
方法控制:
此方法的平台默认实现为每个调用返回一个新的端点实例,从而确保每个客户端有一个端点实例,即默认的部署基数。
这意味着在WebsocketServerEndpoint
类本身中存储特定于会话的状态是安全的,而不必手动将会话与自定义连接实例关联:
@ServerEndpoint("/ws")
public class WebsocketServerEndpoint {
private CustomWebsocketHandler handler;
@OnOpen
public void onOpen(Session session) {
handler = new CustomWebsocketHandler(session);
}
@OnClose
public void onClose(Session session, CloseReason reason) {
handler.handleClose();
}
}
此时,让注释类WebsocketServerEndpoint
本身需要CustomWebsocketHandler
也可能更容易,因为它具有相同的语义:每个连接一个实例并处理websocket事件。