2014-12-05 183 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