Java 永远不会调用WebSocket:OnClose()

Java 永远不会调用WebSocket:OnClose(),java,websocket,encoder,oncloselistener,Java,Websocket,Encoder,Oncloselistener,我正在使用WebSocket端点实现一个应用程序。下面是一些代码: @ApplicationScoped @ServerEndpoint(value="/socket", encoders = {MessageEncoder.class, CommandEncoder.class}) public class SocketEndpoint { /** Default-Logger */ private final static Logger LOG = LoggerFactor

我正在使用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()); 
    }
}
其中一个encode类如下所示:

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();
    }
}
使用此虚拟端点时,正确调用了
@OnClose
。我只能看到
SocketEndpoint
类的一个主要区别:
dummeyendpoint
不使用任何
Encoder


有什么提示吗?

如注释中所述,代码工作正常。如果我们从这一点开始,在
ServerEndpoint
上添加一个
@OnClose
修饰方法,那么使用Wildfly 10.x和最新浏览器(例如Chrome v59.x)就可以很好地工作。ServerEndpoint在此工作的示例(要使用
@Inject
,请不要忘记在WEB-INF文件夹中添加
beans.xml
):

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

如果直接使用wildfly部署,您可以通过删除(从)中的所有内容来清理资源:

  • /[wildfly位置]/standalone/data
  • /[wildfly位置]/standalone/deployments
  • /[wildfly位置]/standalone/tmp

它确保在将来的部署过程中不会保留代码的旧副本。

您使用的是什么应用程序服务器?当你说关闭WebSocket时,你的确切意思是什么?您正在从调用websocket.close()的客户端vi关闭它?还是关闭浏览器?我正在使用Wildfly 10.0.1应用服务器。尝试关闭调用ws.close()的websocket并关闭浏览器。可能与@Duong Nguyen重复。这不是重复。在发布这篇文章之前,我看到了你的意思。我用Firefox、Chrom、IE、Edge和一些用于WebSocket的FF/Chrome插件测试了我的代码。。。另外:我实现的'@OnError'方法也没有被调用。关闭websocket时调用的唯一方法是编码器类中的“@OnDestroy”。使用此方法并添加
OnClose
注释,在关闭选项卡时调用此方法。我使用了wildfly 10.1.0.Final,Java8。您在端点中使用的
SessionHandler
是什么?
@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()); 
    }
}
@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() );
    }
}