WebSocket:永远不会调用 OnClose() [英] WebSocket: OnClose() is never called
问题描述
我正在使用 WebSocket 端点实现一个应用程序.这是一些代码:
I'm implementing an application with a WebSocket endpoint. Here is some code:
@ApplicationScoped
@ServerEndpoint(value="/socket", encoders = {MessageEncoder.class, CommandEncoder.class})
public class SocketEndpoint {
/** Default-Logger */
private final static Logger LOG = LoggerFactory.getLogger(SocketEndpoint.class);
@Inject
SessionHandler sessionHandler;
@OnOpen
public void open(Session session, EndpointConfig config) {
LOG.debug("Connected session => '{}' - '{}'", session, config);
sessionHandler.initSession(session);
}
@OnMessage
public void onMessage(Session session, String messageJson) {
// do something
}
@OnClose
public void onClose(Session session, CloseReason reason) {
LOG.debug("Closing session => '{}' - '{}'", session, reason);
sessionHandler.removeSession(session);
}
@OnError
public void onError(Session session, Throwable ex) {
LOG.error("WebSocket error => '{}'", ex.getMessage());
}
}
其中一个编码类如下所示:
One of the encode class looks like this:
public class MessageEncoder implements Encoder.Text<Message> {
/** Default-Logger */
private final static Logger LOG = LoggerFactory.getLogger(MessageEncoder.class);
@Override
public void init(EndpointConfig config) {
LOG.debug("Init MessageEncoder");
}
@Override
public void destroy() {
LOG.debug("Destroy MessageEncoder");
}
@Override
public String encode(MessageE message) throws EncodeException {
return message.toString();
}
}
打开 WebSocket 会按预期调用 SocketEndpoint.open()
.关闭 WebSocket 只会调用 MessageEncoder.destroy()
而不是 SocketEndpoint.close()
.
Opening the WebSocket calls SocketEndpoint.open()
as expected.
Closing the WebSocket only calls MessageEncoder.destroy()
but not SocketEndpoint.close()
.
谁能给我一个建议,我做错了什么?如果没有解决方案,我将不得不手动检查注册的会话是否仍然存在,因为 MessageEncoder.destroy()
没有参数.
Can anyone give me an advise, what I did wrong? Without a solution I would have to check manually if registered sessions are still alive since MessageEncoder.destroy()
has no parameters.
提前致谢!
更新
刚刚实现了一个虚拟端点:
Just implemented a dummy endpoint:
@ApplicationScoped
@ServerEndpoint("/dummy")
public class DummyEndpoint {
/** Default-Logger */
private final static Logger LOG = LoggerFactory.getLogger(DummyEndpoint.class);
@OnOpen
public void open(Session session, EndpointConfig config) {
LOG.debug("Connected session with principal => '{}'", session.getId());
}
@OnMessage
public void onMessage(Session session, String messageJson) {
LOG.debug("on message => '{}' => '{}'", session.getId(), messageJson);
}
@OnClose
public void onClose(Session session, CloseReason reason) {
LOG.debug("Closing session => '{}' - '{}'", session, reason);
}
@OnError
public void onError(Session session, Throwable ex) {
LOG.error("WebSocket error => '{}' => '{}'", session, ex.getMessage());
}
}
当使用这个虚拟端点时 @OnClose
被正确调用.我只能看到 SocketEndpoint
类的一个主要区别:DummyEndpoint
不使用任何 Encoder
类.
When using this dummy endpoint @OnClose
is properly called. I can only see one major difference to the SocketEndpoint
class: DummyEndpoint
does not use any Encoder
classes.
有什么提示吗?
推荐答案
正如评论中提到的,代码运行得很好.如果我们从这个wildfly-websocket-quickstart开始,添加@OnClose
在 ServerEndpoint
上装饰的方法,它在使用 Wildfly 10.x 和最近的浏览器(例如 Chrome v59.x)时可以正常工作.ServerEndpoint 在这里工作的一个例子(使用 @Inject
不要忘记在 WEB-INF 文件夹中添加一个 beans.xml
):
As mentioned in the comments, the code is working just fine. If we start from this wildfly-websocket-quickstart, adding an @OnClose
decorated method on the ServerEndpoint
, it works fine using Wildfly 10.x, and recent browsers (for instance Chrome v59.x). An example of ServerEndpoint working here (to use @Inject
don't forget to add a beans.xml
in WEB-INF folder):
@ApplicationScoped
@ServerEndpoint(value="/shout", encoders = {MessageEncoder.class})
public class ShoutServerEndpoint {
@Inject
SessionHandler s;
@OnOpen
public void open(Session session, EndpointConfig config) throws Exception {
s.initSession(session);
}
@OnMessage
public void shout(String text, Session client) {
System.out.println("Session: " + client + " has text: " + text);
Message m = new Message();
try {
client.getBasicRemote().sendObject(m);//use the encoder to write some dummy message
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (EncodeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
client.getAsyncRemote().sendText(text.toUpperCase());
}
@OnClose
public void onClose(Session client, CloseReason reason){
System.out.println("Session " + client + " closing for " + reason);
s.destroySession(client);
}
@OnError
public void onError(Session session, Throwable ex) {
System.out.println("error: " + ex.getMessage() );
}
}
因此,罪魁祸首似乎是在重新部署 web 应用程序期间没有清理 wildfly 使用的旧版本代码,例如,使用 Eclipse,在出现奇怪行为的情况下值得使用 <使用的服务器上的 code>Clean 选项(请参阅:这个 Eclipse 文档)
Thus the culprit seems to be that there is an older version of the code used by wildfly that was not cleaned during a redeployment of the webapp, for instance, using Eclipse, it is worth in case of strange behavior to use the Clean
option on the server used (see: this Eclipse doc)
如果直接使用 wildfly 部署,您可以通过删除所有内容来清理资源(来自 这篇文章):
If deploying directly with wildfly, you can clean your resources by deleting everything in (from this article):
/[wildfly-location]/standalone/data
/[wildfly-location]/standalone/deployments
/[wildfly-location]/standalone/tmp
它确保在未来部署期间不会保留您的代码的旧副本.
It ensures no older copies of your code remains during a future deployment.
这篇关于WebSocket:永远不会调用 OnClose()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!