我在我的Spring MVC应用程序中使用Atmosphere来促进推送,使用streaming
传输。
在我的应用程序的整个生命周期中,客户端将订阅和取消订阅许多不同的主题。
Atmosphere似乎每个订阅使用一个http连接 - 即,每次调用$.atmosphere.subscribe(request)
都会创建一个新连接。这很快就会耗尽从浏览器到大气服务器的连接数量。
我不希望每次都创建新资源,而是希望能够在初始创建后向广播公司添加和删除AtmosphereResource
。
但是,由于AtmosphereResource
是入站请求的一对一表示,每次客户端向服务器发送请求时,它都会到达新的AtomsphereResource
,这意味着我有无法引用原始资源,并将其附加到主题Broadcaster
。
我尝试在原始$.atmosphere.subscribe(request)
调用返回的资源上同时使用atmosphereResource.push(request)
和调用subscribe()
。但是,这没有任何区别。
解决这个问题的正确方法是什么?
答案 0 :(得分:9)
以下是我如何运作:
首先,当客户端进行初始连接时,请确保在调用suspend()
之前浏览器接受特定于大气的标头:
@RequestMapping("/subscribe")
public ResponseEntity<HttpStatus> connect(AtmosphereResource resource)
{
resource.getResponse().setHeader("Access-Control-Expose-Headers", ATMOSPHERE_TRACKING_ID + "," + X_CACHE_DATE);
resource.suspend();
}
然后,当客户端发送其他订阅请求时,虽然它们来自不同的resource
,但它们包含原始资源的ATMOPSHERE_TRACKING_ID
。这允许您通过resourceFactory
:
@RequestMapping(value="/subscribe", method=RequestMethod.POST)
public ResponseEntity<HttpStatus> addSubscription(AtmosphereResource resource, @RequestParam("topic") String topic)
{
String atmosphereId = resource.getResponse().getHeader(ATMOSPHERE_TRACKING_ID);
if (atmosphereId == null || atmosphereId.isEmpty())
{
log.error("Cannot add subscription, as the atmosphere tracking ID was not found");
return new ResponseEntity<HttpStatus>(HttpStatus.BAD_REQUEST);
}
AtmosphereResource originalResource = resourceFactory.find(atmosphereId);
if (originalResource == null)
{
log.error("The provided Atmosphere tracking ID is not associated to a known resource");
return new ResponseEntity<HttpStatus>(HttpStatus.BAD_REQUEST);
}
Broadcaster broadcaster = broadcasterFactory.lookup(topic, true);
broadcaster.addAtmosphereResource(originalResource);
log.info("Added subscription to {} for atmosphere resource {}",topic, atmosphereId);
return getOkResponse();
}