Java Servlet 不会停止推送通知

Java Servlet does not stop Push notifications

本文关键字:通知 Servlet Java      更新时间:2023-09-26

我有一个servlet,它将HTML5服务器发送的事件发送到jsp客户端。servlet 每隔一秒向客户端发送一次数据。jsp 客户端实例化一个新的事件源并接收数据。当窗口即将关闭时,jsp 客户端会在"beforeunload"事件处关闭事件源(如下面的代码所示(。

但是,我注意到,即使在客户端关闭事件源并且浏览器退出之后,服务器仍会继续发送数据。就 eventsource 的文档而言,使用 eventsource.close(( 足以阻止客户端重新连接到服务器,并且服务器将停止发送任何进一步的推送通知。

编辑:我已经阅读了有关StackOverflow的类似问题 此链接 .但是,答案是在聊天中讨论的,因此无法访问它。

任何人都可以帮助我理解为什么即使在 eventsource.close(( 和浏览器退出后服务器也不会停止发送推送通知?我是否编写任何其他代码段来通知服务器在客户端退出后停止发送数据?

感谢您的帮助。 这是我简化的服务器代码:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
/**
 * Servlet implementation class ServletForSSE
 */
@WebServlet("/ServletForSSE")
public class ServletForSSE extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServletForSSE() {
      super();
      // TODO Auto-generated constructor stub
    }
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
      //content type must be set to text/event-stream
      response.setContentType("text/event-stream");   
     //encoding must be set to UTF-8
     response.setCharacterEncoding("UTF-8");
     PrintWriter writer = response.getWriter();
     SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss.SSS");
     int i=0;
     while (i<1000) {   
        i++;
        System.out.println("------"+ sdf.format(System.currentTimeMillis()).toString());
        writer.write("data: "+ sdf.format(System.currentTimeMillis()).toString()+"'n" +"'n'n");
        writer.flush();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
    }
}

下面是客户端代码:

    <!DOCTYPE HTML>
     <html>
     <body>
     Time: <span id="foo"></span>
    <br><br>
    <button onclick="start()">Start</button>
    <script type="text/javascript">
    var eventSource;
    function start() {
         eventSource = new EventSource("ServletForSSE");
        eventSource.onmessage = function(event) {
            document.getElementById('foo').innerHTML += event.data+"<br/>";
        };
    }
    function beforeLeaving(){
         if (window.addEventListener) {  // all browsers except IE before version 9
                window.addEventListener ("beforeunload", OnBeforeUnLoad, false);
            }
            else {
                if (window.attachEvent) {   // IE before version 9
                    window.attachEvent ("onbeforeunload", OnBeforeUnLoad);
                }
            }
        console.log("Before Leaving");
    }
    beforeLeaving();
    // the OnBeforeUnLoad method will only be called in Google Chrome and Safari
   function OnBeforeUnLoad () {
        console.log("Taskss");
        eventSource.close();
        console.log(eventSource.==true);
       return "All data that you have entered will be lost!";
   }
    </script>
</body>
</html>

一种检查连接已关闭的方法是使用 writer.checkError() 方法,Servlet 连接已关闭。我在Chrome上测试了此修复程序,它可以工作。您的代码将是:

            boolean error=false;
            while (!error && (i<1000)) {
                //...                   
                writer.write("data: " + /*... + */  "'n'n");
                //writer.flush();
                error = writer.checkError();    //internally calls writer.flush()
                //... 
            }

详情

PrintWriter的API说:

此类中的方法从不引发 I/O 异常,尽管它的某些 构造函数可以。客户可以询问是否有任何错误 通过调用 checkError() 发生。

和 checkError(( 说:

如果流未关闭,则刷新流并检查其错误状态