WebSocket:从不调用 OnClose()

2022-09-04 04:34:56

我正在实现一个具有WebSocket端点的应用程序。下面是一些代码:

@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()); 
    }
}

其中一个编码类如下所示:

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 调用。关闭 WebSocket 仅调用,而不调用 。SocketEndpoint.open()MessageEncoder.destroy()SocketEndpoint.close()

任何人都可以给我一个建议,我做错了什么?如果没有解决方案,我必须手动检查已注册的会话是否仍然有效,因为没有参数。MessageEncoder.destroy()

提前致谢!


更新

刚刚实现了一个虚拟端点:

@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()); 
    }
}

使用此虚拟终结点时,请正确调用。我只能看到该类的一个主要区别:不使用任何类。@OnCloseSocketEndpointDummyEndpointEncoder

任何提示?


答案 1

如注释中所述,代码工作正常。如果我们从这个 wildfly-websocket 快速入门开始,在 上添加一个修饰的方法,使用 Wildfly 10.x 和最近的浏览器(例如 Chrome v59.x)可以正常工作。ServerEndpoint在这里工作的一个例子(要使用,不要忘记添加一个在WEB-INF文件夹中):@OnCloseServerEndpoint@Injectbeans.xml

@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() );
    }
}

因此,罪魁祸首似乎是wildfly使用的代码的旧版本在重新部署webapp期间未被清除,例如,使用Eclipse,如果出现奇怪的行为,值得在所使用的服务器上使用该选项(请参阅:此Eclipse docClean)

如果直接使用 wildfly 进行部署,则可以通过删除(来自本文)中的所有内容来清理资源:

  • /[wildfly-location]/standalone/data
  • /[wildfly-location]/standalone/deployments
  • /[wildfly-location]/standalone/tmp

它可确保在将来的部署期间不会保留较旧的代码副本。


答案 2

推荐