Jersey SSE事件输出写入不会到客户端,除非关闭



我有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());
});
这是使用eventoutput 推送消息的服务器代码
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()的解决方案,它有助于刷新消息,但当然有关闭连接的副作用。虽然连接从客户端自动重新创建,但我只是想了解为什么在我的情况下需要关闭?有人遇到过类似的问题吗?

是否与一些标准响应流缓冲区大小有关?我的消息是由用户输入的聊天字符串,长度可以是偶数个字符。

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

我和你有同样的问题,最后在打开wireshark后找到了它。也就是说,数据只在HTTP响应体上发送,而不是流化/分块。换句话说,如果没有显式调用eventOutput.close,它将不会被发送。

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

最后,检查java web应用程序上是否有可能收集响应的过滤器。在我的例子中,是Dropwizard中的gzip过滤器阻止了TCP数据包的发送。

我在JERSEY-jira上写了更多的细节

我也有同样的问题,我解决了在我的ResourceConfig.java中删除,如果你有:

EncodingFilter.enableFor(this, GZipEncoder.class);

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

最新更新