Java Servlet不会停止推送通知

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

但是,我注意到即使客户端关闭了事件源并且浏览器退出,服务器也会继续发送数据。 至于有关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); } } 

这是客户端代码:

     Time:  

var eventSource; function start() { eventSource = new EventSource("ServletForSSE"); eventSource.onmessage = function(event) { document.getElementById('foo').innerHTML += event.data+"
"; }; } 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!"; }

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的API说:

这个类中的方法永远不会抛出I / Oexception,尽管它的一些构造函数可能会。 客户端可以通过调用checkError()来查询是否发生了任何错误。

并且checkError()说:

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