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