2014-12-05 88 views
2

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

但是,我注意到,即使在客户端关闭事件源并且浏览器退出后,服务器仍会继续发送数据。就eventource文档而言,使用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> 
+0

当你的循环完就叫writer.close(); – Raju 2015-04-29 07:20:32

+0

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''doGet()'退出后可能会隐式调用'writer.close()''''',当客户关闭并且环路尚未完成时,他正在为IMO提供帮助。 – Ricardo 2015-07-24 23:26:38

+0

抽象代码上的差异,它似乎是一样的问题http://stackoverflow.com/questions/25572667/connection-close-in-java-servlet-and-sse – Ricardo 2015-07-29 00:06:56

回答

1

的一种方式,wihin的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说:

方法在这个类不会抛出I/O异常,尽管它的一些 构造的可能。客户可以通过调用checkError()来询问是否发生了错误 。

checkError()说:

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

+0

我也发布了解决方案的另一个问题和给我的朋友Shuge Li和Enyong Chen,还没有在这个社区给学分。 – Ricardo 2015-07-29 23:33:01