java - 服务器发送的事件丢失连接

标签 java jersey server-sent-events

我正在关注this tutorial我将返回的数据放在 Chrome 的控制台日志中。这是我在客户端的代码:

$(document).ready(function() {  

  //check for browser support
  if(typeof(EventSource)!=="undefined") {

    var source = new EventSource("URL/sse");
    //detect message receipt       
    source.addEventListener("message", function(e) {
        console.log(e.data);            
    }, false);

    source.addEventListener("open", function(e) {
        console.log("Connection was opened.");
    }, false);


    source.addEventListener("error", function(e) {
        if (e.readyState == EventSource.CLOSED) {
            console.log("Connection lost.");
        }            
    }, false);
  }
  else {
    // No support
  }
});

数据没问题。当我访问网页时,我的控制台日志每 3 秒打开和关闭一次连接:

mypage.js:39 Connection was opened.
mypage.js:15 [{"John":"1","Doe":"2"}]
mypage.js:44 Error - Connection lost.
// 3 seconds
mypage.js:39 Connection was opened.
mypage.js:15 [{"John":"1","Doe":"2"}]
mypage.js:44 Error - Connection lost.
// 3 seconds
mypage.js:39 Connection was opened.
mypage.js:15 [{"John":"1","Doe":"2"}]
mypage.js:44 Error - Connection lost.
...

这是我的服务器端代码:

@Singleton
@Path("/sse")
public class SSEResource {

  @GET
  @Produces(SseFeature.SERVER_SENT_EVENTS)
  public EventOutput getServerSentEvents() {
    final EventOutput eventOutput = new EventOutput();

    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                final OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
                eventBuilder.name("message");

                final String myString = getData.toString(); // Some data from db

                eventBuilder.data(String.class, myString);

                final OutboundEvent event = eventBuilder.build();
                eventOutput.write(event);

            } catch (Exception e) {
                throw new RuntimeException("Error when writing the event.",
                        e);
            } finally {

                try {
                    eventOutput.close();
                } catch (IOException ioClose) {
                    throw new RuntimeException(
                            "Error when closing the event output.", ioClose);
                }
            }
        }
    }).start();
    return eventOutput;
  }
}

据我了解,连接应保持打开状态,直到客户端决定关闭它。我究竟做错了什么?这是正确的吗?

最佳答案

您的服务器代码正在关闭 EventOutput。

           try {
                eventOutput.close();
            } catch (IOException ioClose) {
                throw new RuntimeException(
                        "Error when closing the event output.", ioClose);
            }

这会导致客户端重新连接并且进程再次开始。

我不是 100% 确定你在做什么。如果要在线程中发送更多数据,则不需要关闭EventOutput。

根据规范,您可以发送 HTTP 204 No Content 响应代码来阻止客户端重新连接,但我不确定如何使用 Jersey SSE 来执行此操作。当我遇到这个问题时,我正在寻找答案。

在您的情况下,您可以发送一条消息,导致客户端关闭连接,或阻止其重新连接。

关于java - 服务器发送的事件丢失连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31987130/

相关文章:

jquery - 更改从服务器发送的事件生成的元素的 CSS

flutter - Flutter服务器端事件,响应式(Reactive)UI

java 连接到 jabber

java - Java中访问/修改最快的数据结构

java - 使用 Jersey Client POST 方法调用 RESTful Web 服务时出错

web-services - 在虚拟机上通过Jersey部署REST服务时出错

ruby-on-rails - SSE 消息是否通过 https 连接加密?

java - 当 TextView 在 fragment 内的 onLocationChanged 内更改时应用程序崩溃

java - 在 Java 文本文件中使用字符串对数字进行排序

java - 如何在 JAX-RS 中为子资源中的子资源设计路径?