【问题标题】:Jersey SSE Eventoutput writes are not going to client unless closedJersey SSE Eventoutput 写入不会发送到客户端,除非关闭
【发布时间】:2014-09-22 08:57:52
【问题描述】:

我有 jquery 客户端期待来自 java servlet/JAX-RS 服务器的 Jersey SSE 事件。

我有这个客户端代码向服务器发起请求

var source = new EventSource("api/chat");
$(source).on("message", function (evt) {
    var chatMsg = JSON.parse(evt.originalEvent.data);    
    $("#chat").val(chatMsg.userid + ": " + chatMsg.msg + "\n" + $("#chat").val());
});

这是使用事件输出推送消息的服务器代码

JsonObject obj = Json.createObjectBuilder()
                .add("userid", userid)
                .add("msg", msg)
                .build();
OutboundEvent evt = new OutboundEvent.Builder()
                .mediaType(MediaType.APPLICATION_JSON_TYPE)
                .data(JsonObject.class, obj)
                .build();   

eventOutput.write(evt);
eventOutput.close();

这里发生的情况是,如果没有使用eventoutput.close(),客户将没有得到任何响应。

根据文档,这种关闭不是必需的,或者至少在任何地方都没有提及。但是如果没有这些消息,它们就会排队,只有当我尝试关闭服务器时才会传递它们。那很奇怪。 我找到了close() 的解决方法,它有助于刷新消息,但当然会产生关闭连接的副作用。虽然连接是从客户端自动重新创建的,但我只是想了解为什么在我的情况下需要关闭? 有没有人遇到过类似的问题?

这与某些标准响应流缓冲区大小有关吗?我的消息是用户输入的聊天字符串,长度甚至可以是 1 个字符。

我正在使用 GlassFish server 4 和 jersey 2.9.1 版本的 jar。浏览器是chrome。

【问题讨论】:

    标签: jakarta-ee servlets jersey-2.0


    【解决方案1】:

    EventSource 不是 jQuery 对象(除非您正在加载某种插件)。

    source.addEventListener('message', function(e) {
        console.log(e.data);
    }, false);
    
    source.addEventListener('open', function(e) {
        // Connection was opened.
    }, false);
    
    source.addEventListener('error', function(e) {
        if (e.readyState == EventSource.CLOSED) {
            // Connection was closed.
        }
    }, false);
    

    【讨论】:

    • 这个答案与我的问题完全无关。正如我之前提到的,我在客户端收到消息,显式调用关闭服务器,或者如果我尝试关闭服务器。顺便说一句,即使 eventsource 不是 jquery 对象,我也会在调用它的方法之前像 $(source) 一样包装它。原始问题中给出的 Jquery 代码非常好。只是该服务器无法在没有密切联系的情况下推送。
    • 明白。如您所示,我尝试使用 jQuery 包装器,但无法使其正常工作。我不得不使用原生的onMessage 处理程序。另外,我在 Glassfish 推广的 build b08 上运行,其中包括 Jersey 2.10.1。
    【解决方案2】:

    我遇到了和你一样的问题,打开wireshark后终于解决了。也就是说,数据仅在 HTTP 响应正文上发送,而不是流式传输/分块输入。换句话说,如果 eventOutput.close 没有被显式调用,它就不会被发送。

    首先,检查您的代理(如果您正在使用代理)以确保那一侧没有缓冲。

    最后,检查您的 java webapp 上是否有任何过滤器可以收集响应。在我的例子中,是 Dropwizard 中的 gzip 过滤器阻止了 TCP 数据包的发送。

    我在JERSEY-jira写了更详细的文章

    【讨论】:

      【解决方案3】:

      我有同样的问题, 我在 ResourceConfig.java 中解决了 REMOVING,如果您有:

      EncodingFilter.enableFor(this, GZipEncoder.class);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-06
        • 2016-11-21
        • 2014-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-05
        • 1970-01-01
        相关资源
        最近更新 更多