【问题标题】:Java Servlet does not stop Push notificationsJava Servlet 不会停止推送通知
【发布时间】:2014-12-05 08:58:55
【问题描述】:

我有一个 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>

【问题讨论】:

  • 当你的循环结束时,只需调用 writer.close();
  • writer.close() 可能会在doGet() 退出后被隐式调用,这也应该停止发送推送通知。当客户端关闭并且循环尚未完成时,他要求 IMO。
  • 在代码上抽象差异,好像和stackoverflow.com/questions/25572667/…一样的问题

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


【解决方案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() 说:

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

【讨论】:

  • 另外一个问题的答案我也发布了,感谢我的朋友Shuge Li 和 Enyong Chen,还没有加入这个社区。​​span>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
相关资源
最近更新 更多