Javascript 和 Java 的 Web Socket 问题 - 未捕获的 DOMException:尝试使用不可用或不再可用的对象

Posted

技术标签:

【中文标题】Javascript 和 Java 的 Web Socket 问题 - 未捕获的 DOMException:尝试使用不可用或不再可用的对象【英文标题】:Web Socket Problem with Javascript and Java - Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable 【发布时间】:2020-10-22 18:17:10 【问题描述】:

我正在尝试在 js 和 java 之间建立 Web 套接字连接,但我得到了这个答案:未捕获的 DOMException:尝试使用不是或不再是的对象,可用 我是根据互联网上的一些样本来做的。有人知道它是什么吗? 项目名称是 Teste-1

JS 代码

var socket = null;
function init()
    socket = new WebSocket("wss://localhost:8080/Teste-1/task");    
    socket.onmessage = onMessage;
    


function onMessage(event)
     var task = JSON.parse(event.data);
     if(task.action === "add")
         document.getElementById("point").innerhtml += event.data;
                     


function teste() 
    var action = 
        action: "add",
        name: "Test",
        description: "This is just a test"
    ;
    socket.send(JSON.stringify(action));

window.onload = init;

HTML 代码

<html>
    <head>
        <title>Test</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        
    </head>
    <body>
        <button onclick="teste()">Teste</button>
        <div id="point"></div>
        <script src="websocket.js"></script>
    </body>
</html>

JAVA 代码

public class Task implements Serializable
    private static final long serialVersionUID = 1L;
    private String name;
    private String description;
    
    public Task()

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getDescription() 
        return description;
    

    public void setDescription(String description) 
        this.description = description;
    
 
@ServerEndpoint(value="/task")
public class TaskSocket 
    @Inject
    private TaskSessionHandler handler;
    
    @OnOpen
    public void open(Session session)
        handler.addSession(session);
    
    
    @OnClose
    public void close(Session session)
        handler.removeSession(session);
    
    
    @OnError
    public void onError(Throwable error)
        Logger.getLogger(TaskSocket.class.getName()).log(Level.SEVERE, null, error);
    
    
    @OnMessage
    public void handleMessage(String message, Session session) 
        try (JsonReader reader = Json.createReader(new StringReader(message))) 
            JsonObject jsonMessage = reader.readObject();

            if ("add".equals(jsonMessage.getString("action"))) 
                Task task = new Task();
                task.setName(jsonMessage.getString("name"));
                task.setDescription(jsonMessage.getString("description"));
                
                handler.addTask(task);
            

            
        
    



@ApplicationScoped
public class TaskSessionHandler 
    //Each client connected to the application has its own session.
    private final Set<Session> sessions = new HashSet<>();
    private final Set<Task> tasks = new HashSet<>();
    
    public void addSession(Session session) 
        sessions.add(session);
        for(Task task : tasks)
            JsonObject addMessage = createJSON(task);
            sendToSession(session, addMessage);
        
    

    public void removeSession(Session session) 
        sessions.remove(session);
    
    
    public List<Task> getTasks()
        List<Task> list = new ArrayList<Task>(tasks);
        return list;
    
    
    public void addTask(Task e)
        tasks.add(e);
        JsonObject message = this.createJSON(e);
        sendToAllConnectedSessions(message);
    
    
    private JsonObject createJSON(Task task)
        JsonProvider provider = JsonProvider.provider();
        JsonObject message = provider.createObjectBuilder()
                .add("action", "add")
                .add("name",task.getName())
                .add("description",task.getDescription()).build();
        return message;
    
    
     private void sendToAllConnectedSessions(JsonObject message) 
        for (Session session : sessions) 
            sendToSession(session, message);
        
    
    
    private void sendToSession(Session session, JsonObject message) 
        try 
            session.getBasicRemote().sendText(message.toString());
         catch (IOException ex) 
            sessions.remove(session);
            Logger.getLogger(TaskSessionHandler.class.getName()).log(Level.SEVERE, null, ex);
        
    
    

【问题讨论】:

【参考方案1】:

由于在与 webSocket 服务器的连接建立并打开之前执行了 websocket.send(),我收到了相同的错误消息。

我的贡献是建议确保在连接打开之前不会发送消息,以便服务器实际上可以接收它们。

我不知道这是否是问题中的问题。然而,我遇到了一个非常相似的问题并最终来到这里,并想分享对我有用的方法。

在我的例子中,不起作用的代码如下所示:

const exampleSocket = new WebSocket('wws://example')

exampleSocket.onopen = function (event) 
  console.log('connection is open!')


exampleSocket.send(JSON.stringify(msg))

exampleSocket.onmessage = function (event) 
  console.log('message event data looks like this: ', event.data)

起作用的是将发送消息的代码移动到 onopen 回调函数中。

const exampleSocket = new WebSocket('wws://example')
    
    exampleSocket.onopen = function (event) 
      console.log('connection is open!')
      exampleSocket.send(JSON.stringify(msg))             // <- this is the change
    
    
    exampleSocket.onmessage = function (event) 
      console.log('message event data looks like this: ', event.data)
    

旁注:websocket 的 readyState 属性在处理确保服务器已准备好接收消息时可能很有用。

如果是1,表示连接打开,可以这样使用:

if (exampleSocket.readyState  === 1) 
     console.log("It is safe to send messages now")

【讨论】:

以上是关于Javascript 和 Java 的 Web Socket 问题 - 未捕获的 DOMException:尝试使用不可用或不再可用的对象的主要内容,如果未能解决你的问题,请参考以下文章

Java 之 web 相关概念

Javascript 和 Java 的 Web Socket 问题 - 未捕获的 DOMException:尝试使用不可用或不再可用的对象

Java Web 前言和体系结构

Java Web高级编程

Java Web-JavaScript

javascript、JSP、JS有啥区别和联系