Java Servlet does not stop Push notifications

爷,独闯天下 提交于 2019-12-07 20:27:09

问题


I have a servlet which sends HTML5 server sent events to the jsp client. The servlet sends data to the client every one second. The jsp client instantiates a new eventsource and recieves the data. When the window is about to close, the jsp client closes eventsource at the "beforeunload" event (shown in the code below).

However, I have noticed that even after the client closes the eventsource and the browser exits, the server continues sending data. As far as the documentation on eventsource goes, using eventsource.close() is enough to stop client from reconnecting to the server and the server will stop sending any further push notifications.

EDIT : I have read through a similar question on StackOverflow at this link . However, the answer was discussed on a chat and hence do not have access to it.

Can any one please help me understand why the server does not stop sending push notifications even after eventsource.close() and the browser exit? Do I write any other piece of code to notify the server to stop sending data once client exits?

Thanks for help. Here is my simplified server code:

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);
    }

}

Here is the client code:

    <!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:


One way to check, wihin the Servlet, that connection is closed, is using the writer.checkError() method. I tested this fix on Chrome and it works. Your code would be:

            boolean error=false;
            while (!error && (i<1000)) {
                //...                   
                writer.write("data: " + /*... + */  "\n\n");
                //writer.flush();
                error = writer.checkError();    //internally calls writer.flush()
                //... 
            }

Details:

The PrintWriter's API says:

Methods in this class never throw I/O exceptions, although some of its constructors may. The client may inquire as to whether any errors have occurred by invoking checkError().

and the checkError() says:

Flushes the stream if it's not closed and checks its error state



来源:https://stackoverflow.com/questions/27312151/java-servlet-does-not-stop-push-notifications

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!