gpt4 book ai didi

html - 为什么 DeferredResult 在尝试使用 SSE 时以 setResult() 结束

转载 作者:行者123 更新时间:2023-11-27 23:52:49 25 4
gpt4 key购买 nike

我正在尝试实现一个由 Spring 提供支持的服务器发送事件 (SSE) 网页。我的测试代码执行以下操作:

浏览器使用 EventSource(url) 连接到服务器。 Spring 接受带有以下 Controller 代码的请求:

@RequestMapping(value="myurl", method = RequestMethod.GET, produces = "text/event-stream")
@ResponseBody
public DeferredResult<String> subscribe() throws Exception {
final DeferredResult<String> deferredResult = new DeferredResult<>();
resultList.add(deferredResult);

deferredResult.onCompletion(() -> {
logTimer.info("deferedResult "+deferredResult+" completion");
resultList.remove(deferredResult);
});
return deferredResult;
}

所以主要是它将 DeferredResult 放在一个列表中并注册一个完成回调,这样我就可以在完成时从列表中删除这个东西。

现在我有一个计时器方法,它会通过它们的 DeferredResults 定期将当前时间戳输出到所有已注册的“浏览器”。

@Scheduled(fixedRate=10000)
public void processQueues() {
Date d = new Date();
log.info("outputting to "+ LoginController.resultList.size()+ " connections");
LoginController.resultList.forEach(deferredResult -> deferredResult.setResult("data: "+d.getTime()+"\n\n"));
}

数据被发送到浏览器,下面的客户端代码工作:

 var source = new EventSource('/myurl');
source.addEventListener('message', function (e) {
console.log(e.data);
$("#content").append(e.data).append("<br>");
});

现在的问题:

DeferredResult 的完成回调在计时器线程中的每个 setResult() 调用中被调用。因此由于某种原因,连接在 setResult() 调用后关闭。浏览器中的 SSE 按照规范重新连接,然后又是同样的事情。所以在客户端我有一个轮询行为,但我想要一个保持打开的请求,我可以在同一个 DeferredResult 上一遍又一遍地推送数据。

我在这里错过了什么吗? DeferredResult 不能发送多个结果吗?我在计时器线程中延迟了 10 秒,以查看请求是否仅在 setResult() 之后终止。因此在浏览器中,请求一直保持打开状态,直到计时器推送数据,然后关闭。

感谢您对此的任何提示。请注意:我为 tomcat 中的所有过滤器/servlet 添加了异步支持。

最佳答案

确实 DeferredResult 只能设置一次(注意 setResult 返回一个 bool 值)。它使用完整的 Spring MVC 处理选项完成处理,也就是说,除了异步生成的返回值外,您对 Spring MVC 请求期间发生的事情的了解或多或少保持不变。

SSE 需要的是更有针对性的东西,即使用 HttpMessageConverter 将每个值写入响应。我已经为那个 https://jira.spring.io/browse/SPR-12212 创建了一张票.

请注意,Spring 的 SockJS 支持确实有一个 SSE 传输,它负责一些额外的功能,例如使用 cookie 的跨域请求(对 IE 很重要)。它还在 WebSocket API 和 WebSocket 风格的消息传递之上使用(即使 WebSocket 在客户端或服务器端都不可用)完全抽象了 HTTP 长轮询的细节。

作为解决方法,您还可以使用 HttpMessageConverter 直接写入 Servlet 响应。

关于html - 为什么 DeferredResult 在尝试使用 SSE 时以 setResult() 结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25880456/

25 4 0
文章推荐: jquery - 如何使 Bootstrap 列的高度相同,然后管理内部元素的高度?
文章推荐: javascript - Bluebird promise 收集所有结果解决或拒绝
文章推荐: html - MVC : Populate a