有没有办法处理每个 session 的 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
将处理程序直接添加到特定 session 。但是如何为该特定 session 上的 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
中的每个 session 及其各自的 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);
服务器端是否存在类似的情况,或者是否可以完全处理每个 session 的服务器端 onClose
(最终还有 onError
)事件?
最佳答案
默认情况下,会为每个新客户端创建 ServerEndpoint
注释类的新实例。此行为由 ServerEndpointConfig.Configurator#getEndpointInstance
控制方法:
The platform default implementation of this method returns a new endpoint instance per call, thereby ensuring that there is one endpoint instance per client, the default deployment cardinality.
这意味着可以安全地将特定于 session 的状态存储在 WebsocketServerEndpoint
类本身中,而无需手动将 session 与自定义连接实例关联起来:
@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 事件。
关于java - Websocket服务器: Handle close event per session,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46341161/