我们有一个带有仪表板的 Web 应用程序,它不断地轮询更新。在服务器端,更新请求是异步的,因此我们可以通过监听器/通知系统在发生更新时做出响应。
我们看到的问题是,当其中一个轮询请求得到响应时,在某些情况下,它可能会写入请求/响应以获取用户点击的链接。
异步更新的传入请求如下所示:
@RequestMapping("/getDashboardStatus.json")
public void getDashboardStatus(HttpServletRequest request, ...) {
final AsyncContext asyncContext = request.startAsync();
// 10 seconds
asyncContext.setTimeout(10000);
asyncContext.start(new Runnable() {
public void run() {
// .. (code here waits for an update to occur) ..
sendMostRecentDashboardJSONToResponse(asyncContext.getResponse());
if (asyncContext.getRequest().isAsyncStarted()) {
asyncContext.complete();
}
}
});
}
奇怪的地方在于,这个仪表板上有指向其他页面的链接。每大约 100 次左右的点击,其中一次将而不是显示所选页面,实际上显示上面发送的 JSON!
例如,我们有一个单独的 MVC 方法:
@RequestMapping("/result/{resultId}")
public ModelAndView getResult(@PathVariable String resultId) {
return new ModelAndView(...);
}
当点击仪表板上访问 /result/1234
的链接时,每个蓝月亮,页面将加载 200 OK 状态,但不包含预期的 HTML,实际上包含轮询请求的 JSON!
每个客户端只允许一个请求吗?由单击的链接发起的请求是否会覆盖来自同一客户端的任何已经位于服务器端的异步请求?
我们如何管理这些请求以确保异步响应发送到 async 请求?
我注意到 AsyncContext
对象上有一个 hasOriginalRequestAndResponse()
方法,但我很难从 Javadoc 中理解它是否是我正在寻找的。p>
更新:我刚刚添加了一个这样的片段:
String requestURI = ((HttpServletRequest)asyncContext.getRequest()).getRequestURI());
System.out.println("Responding w/ Dashboard to: " + requestURI);
sendMostRecentDashboardJSONToResponse(asyncContext.getResponse(), clientProfileKey);
并且能够在正确行为期间重现该问题,我看到:
Responding w/ Dashboard to: /app/getDashboardStatus.json
但是当我看到 JSON 推送到点击发起的请求时,我看到了:
Responding w/ Dashboard to: null
最佳答案
我已经弄清楚了这一点。请求/响应 确实被回收了,所以通过卡在分配给 AsyncContext
的响应上,我正在写出与 关联的响应不同的请求。
调用 startAsync()
保证请求/响应对象在异步上下文完成之前不会被回收。尽管我发现没有地方会过早或错误地完成上下文,但它正在完成:
超时。
在没有服务器端 Activity 的情况下等待 10 多秒,让 JSON 更新请求超时,然后然后单击链接,我能够始终如一地重现此问题。超时后,与异步上下文相关的请求/响应超时,从而完成,从而回收。
我发现了两个解决方案。
首先是在上下文中添加一个AsyncListener
,并跟踪是否发生了超时。当您的监听器检测到超时时,您会翻转一个 boolean
,并在写入响应之前对其进行检查。
second 是在写入响应之前对请求简单地调用 isAsyncStarted()
。如果上下文超时,此方法将返回 false
。如果上下文仍然有效/等待,它将返回 true
。
https://stackoverflow.com/questions/27711105/
相关文章:
java - 如何覆盖 Spring 3.1 @PropertySource 以设置 IgnoreR
java - 由于 HAL+JSON 媒体类型不明确,无法使用 Spring HATEOAS 执行
spring - IntelliJ + Tomcat + Spring-Loaded
spring - 如何在集成测试阶段使用 Spring 嵌入式数据库初始化脚本?
java - 由于缺少 EmbeddedServletContainerFactory bean,无
java - 使用 mockito 进行 Spring 服务单元测试
java - 如何在 Spring 中构建 SOAP 客户端?
spring - 使用 Spring Security 的 OAuth 2.0 中的 resourc