Java Servlet 不会停止推送通知

标签 java javascript html servlets server-sent-events

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

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

编辑:我已经阅读了 StackOverflow 上的一个类似问题 at this link .但是,答案是在聊天中讨论的,因此无法访问它。

谁能帮我理解为什么即使在 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>

最佳答案

通过 Servlet 检查连接是否关闭的一种方法是使用 writer.checkError() 方法。我在 Chrome 上测试了这个修复程序并且它有效。您的代码将是:

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

详细信息:

PrintWriter's API说:

Methods in this class never throw I/O exceptions, although some of its constructors may. The client may inquire as to whether any errors have occurred by invoking checkError().

checkError()说:

Flushes the stream if it's not closed and checks its error state

关于Java Servlet 不会停止推送通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27312151/

相关文章:

java - openjdk 中的 networkaddress.cache.ttl null

java - 为什么我必须关闭 XSL 中的 <br> 标记?

html - 如何使用 Sass 获取动态列表中的项目数?

Java生成不重复2 ^ 48周期的 "random"数字

java - @After 方法首先由 JUnit 运行

javascript - Codeacademy -列出所有人 - 返回未定义

javascript - 面板内的 CodeMirror 编辑器

html - 图片上的 Z 索引?

Java - 泛型类型的返回类型

javascript - 如何在javascript中修复无序的 "fetch"