Java Servlet不会停止推送通知

时间:2014-12-05 08:58:56

标签: java javascript html5 servlets server-sent-events

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

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

1 个答案:

答案 0 :(得分:1)

检查连接已关闭的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()说:

  

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