Java EE SSE聊天

Java EE SSE聊天,java,jakarta-ee,server-sent-events,Java,Jakarta Ee,Server Sent Events,我想做一个简单的聊天,连接到服务器的用户发送消息,其他用户接收消息 这是我的html: <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <body> <script> function setupEventSource() { var output = document.get

我想做一个简单的聊天,连接到服务器的用户发送消息,其他用户接收消息

这是我的html:

 <%@page contentType="text/html" pageEncoding="UTF-8"%>
 <!DOCTYPE html>
 <html>
   <body>
     <script>
       function setupEventSource() {
         var output = document.getElementById("output");
         if (typeof(EventSource) !== "undefined") {
           var msg = document.getElementById("textID").value;
           var source = new EventSource("TestServlet?msg=" + msg);
           source.onmessage = function(event) {
             output.innerHTML += event.data + "<br>";
           };

           source.addEventListener('close', function(event) {
             alert("Source closed!");
             source.close();
             }, false);
         } else {
           output.innerHTML = "Sorry, Server-Sent Event is not supported in your browser";
         }
         return false;
       }
     </script>

     <h2>Simple SSE Echo Demo</h2>
     <div>
       <input type="text" id="textID" name="message" value="Hello World">
       <input type="button" id="sendID" value="Send" onclick="setupEventSource()"/>
     </div>
     <hr/>
     <div id="output"></div>
   </body>
 </html>
有几件事我不明白:如果我不发送
事件:close
浏览器会每3秒钟发送一次垃圾邮件,这是为什么?我试图通过关闭
EventSource
来避免这种情况,但这是否正确?一旦EventSource关闭,您就不能像刚刚关闭一样打开它,对吗

我还希望所有“已连接的客户端”都能收到消息,但这并没有发生,
数据:
不是应该发送给所有客户端吗


我试过使用chrome和firefox opend并发送消息,我注意到firefox的一些情况:在每次消息后我发送
事件:close
时,消息会每隔6秒发出一次垃圾邮件

您是否正在关闭servlet中的请求?服务器上的SSE请求需要以不同方式处理:

标准Servlet:

  • 请求来自客户端
  • 服务器创建一个响应
  • 服务器将响应发送回客户端
  • 服务器关闭连接
  • 对于SSE,典型流量略有不同。首先,您通常需要创建工作流、servlet工作流(处理连接注册)和事件工作流(处理向注册侦听器发送事件)

    Servlet工作流:

  • 来自客户端的请求(类型为事件流)
  • 服务器将连接缓存在内存中
  • 服务器未关闭连接
  • 事件工作流:

  • 发生了什么事触发了一个事件
  • 服务器获取连接的缓存
  • 对于每个仍然打开的连接,服务器都会写入事件
  • 我的猜测是,当您收到一个事件流请求时,您正在写出您当时拥有的事件,然后关闭连接。这会触发客户端上的EventSource认为它已断开连接或错误关闭,3秒钟后,它尝试向服务器重新注册,整个过程再次发生


    还有一点需要注意。如果您使用的是Servlet,您几乎肯定需要使用异步Servlet API,否则每个连接的客户端都会有一个开放线程。

    使用
    Servlet
    ,您如何知道客户端已关闭EventSource连接?谢谢
        // set content type
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
    
        String msg = request.getParameter("msg");
    
        PrintWriter writer = response.getWriter();
    
        // send SSE
        writer.write("data: " + msg + "\n\n");
        writer.write("event: close\n");
        writer.flush();