【问题标题】:Cannot onmessage with SSE (Java Servlet + ES6 JS)无法使用 SSE 发送消息(Java Servlet + ES6 JS)
【发布时间】:2018-05-16 01:44:21
【问题描述】:

我试图在这个视频https://www.youtube.com/watch?v=rhCKCKD0KnA中做一个 SSE 的例子

    response.setContentType("text/event-stream");
    response.setCharacterEncoding("UTF-8");

    PrintWriter printWriter = null;

    while(true) {

        try {
            double rnd = Math.random() * 10000;

            printWriter = response.getWriter();
            printWriter.print("Rnd: " + rnd);

            response.flushBuffer();


            Thread.sleep(5000);

        }
        catch(IOException | InterruptedException e) {
            e.printStackTrace();

            printWriter.close();

            break;
        }


    }

和客户端

    window.onload = function () {

        startButton.onclick = () => {
            eventSource = new EventSource('http://localhost:8080/byteslounge-1/sse_test');

            eventSource.onopen = () => {
                displayTextArea.value += 'connected...' + '\n';
            };

            eventSource.onmessage = (message) => {
                displayTextArea.value += message.data + '\n\n';
            };

            eventSource.onerror = () => {
                displayTextArea.value += 'error occured...' + '\n';
            };

            startButton.disabled = true;
        };

        takeMsg.onclick = () => {
            eventSource.onmessage = (message) => {
                displayTextArea.value += message.data + '\n\n';
            };
        };

        stopButton.onclick = () => {
            eventSource.close();
            startButton.disabled = false;
        };

        clearText.onclick = () => {
            displayTextArea.value = '';
        }

    }

连接正常,但无法接收 onMessage 中的任何数据。服务器/客户端上没有错误/警告。我正在使用 FF 64 位最新版本/JDK 1.8/Payara。

【问题讨论】:

    标签: java html jakarta-ee long-polling payara


    【解决方案1】:

    我在您的代码中没有发现任何明显的问题。但是,在使用 Payara 5 时,我建议使用 JAX-RS SSE API 而不是自己在 servlet 中编写代码。

    在此处查看示例和指南:http://ridingthecrest.com/blog/2017/02/22/jax-rs-2_1-new-feature-introduction.html

    使用 JAX-RS SSE 替代您的服务器端点:

    @Path("server-sent-events")
    @Singleton
    public class ServerSentEventsResource {
    
        @GET
        @Produces(MediaType.SERVER_SENT_EVENTS)
        public void getMessageQueue(@Context SseEventSink eventSink, @Context Sse sse) {
    
          while(true) {
    
            try {
                double rnd = Math.random() * 10000;
    
                eventSink.send(sse.newEvent("custom-message"));
    
                Thread.sleep(5000);
    
            }
            catch(IOException | InterruptedException e) {
                e.printStackTrace();
    
                printWriter.close();
    
                break;
            }
          }
        }
    }
    

    还可以使用通用 SSE 客户端测试服务器端点,例如curl 支持 SSE 并在传入事件发生时打印它们。如果可行,那么您的 javascript 客户端有错误。

    【讨论】:

    • 问题出在这一行: printWriter.print("Rnd: " + rnd);我不知道,但它的工作原理是这样的(之前有一个字符串“data:”,之后是 \n\n): out.write("data: Rnd: " + String.valueOf(str_rnd) + "\n\ n"); //data: 和 \n\n 是必需的
    • 显然,我错过了。 SSE 要求事件以“\n\ndata:”为前缀,以便客户端可以识别它们。这就是为什么最好使用直接支持 SSE 的 API,比如 Payara 5 中的 JAX-RS 2.1 :)
    • 此外,如果在 Nginx 后面,您必须在标题中添加此响应。否则 Nginx 会缓冲 SSE 响应,无法正常工作:response.setHeader("X-Accel-Buffering","no");
    猜你喜欢
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多