使用 Spring 的 DeferredResult 进行长轮询

Long Polling with Spring's DeferredResult

客户端定期调用异步方法(长轮询),向其传递股票代码的值,服务器使用该值查询数据库,return将对象返回给客户端。

我正在使用 Spring 的 DeferredResult class,但是我不熟悉它的工作原理。请注意我如何使用符号 属性(从客户端发送)来查询数据库中的新数据(见下文)。

也许 Spring 有更好的长轮询方法?

如何将符号 属性 从方法 deferredResult() 传递到 processQueues()

    private final Queue<DeferredResult<String>> responseBodyQueue = new ConcurrentLinkedQueue<>();

    @RequestMapping("/poll/{symbol}")
    public @ResponseBody DeferredResult<String> deferredResult(@PathVariable("symbol") String symbol) {
        DeferredResult<String> result = new DeferredResult<String>();
        this.responseBodyQueue.add(result);
        return result;
    }

    @Scheduled(fixedRate=2000)
    public void processQueues() {
        for (DeferredResult<String> result : this.responseBodyQueue) {
           Quote quote = jpaStockQuoteRepository.findStock(symbol);
            result.setResult(quote);
            this.responseBodyQueue.remove(result);
        }
    }

DeferredResult 在 Spring 4.1.7:

Subclasses can extend this class to easily associate additional data or behavior with the DeferredResult. For example, one might want to associate the user used to create the DeferredResult by extending the class and adding an additional property for the user. In this way, the user could easily be accessed later without the need to use a data structure to do the mapping.

您可以扩展 DeferredResult 并将交易品种参数保存为 class 字段。

static class DeferredQuote extends DeferredResult<Quote> {
    private final String symbol;
    public DeferredQuote(String symbol) {
        this.symbol = symbol;
    }
}

@RequestMapping("/poll/{symbol}")
public @ResponseBody DeferredQuote deferredResult(@PathVariable("symbol") String symbol) {
    DeferredQuote result = new DeferredQuote(symbol);
    responseBodyQueue.add(result);
    return result;
}

@Scheduled(fixedRate = 2000)
public void processQueues() {
    for (DeferredQuote result : responseBodyQueue) {
        Quote quote = jpaStockQuoteRepository.findStock(result.symbol);
        result.setResult(quote);
        responseBodyQueue.remove(result);
    }
}