在Spring MVC流中使用rx-java Observable

Spring MVC现在已经支持异步请求处理流程了一段时间,该支持内部利用了Tomcat / Jetty等容器的Servlet 3异步支持。

Spring Web Async支持

考虑一下需要花一点时间处理的服务呼叫,该服务呼叫具有延迟:

public CompletableFuture<Message> getAMessageFuture() {
    return CompletableFuture.supplyAsync(() -> {
        logger.info("Start: Executing slow task in Service 1");
        Util.delay(1000);
        logger.info("End: Executing slow task in Service 1");
        return new Message("data 1");
    }, futureExecutor);
}

如果要在用户请求流中调用此服务,则传统的阻塞控制器流将如下所示:

@RequestMapping("/getAMessageFutureBlocking")
public Message getAMessageFutureBlocking() throws Exception {
    return service1.getAMessageFuture().get();
}

更好的方法是使用Spring异步支持,以便在CompletableFuture可用时将结果返回给用户,这样就不会占用容器线程了:

@RequestMapping("/getAMessageFutureAsync")
public DeferredResult<Message> getAMessageFutureAsync() {
    DeferredResult<Message> deffered = new DeferredResult<>(90000);
    CompletableFuture<Message> f = this.service1.getAMessageFuture();
    f.whenComplete((res, ex) -> {
        if (ex != null) {
            deffered.setErrorResult(ex);
        } else {
            deffered.setResult(res);
        }
    });
    return deffered;
}

在异步流中使用Observable

现在到本文的主题,最近我一直在使用Rx-java的出色的Observable类型作为我的服务返回类型,并希望确保Web层在处理从服务调用返回的Observable类型时也保持异步。

考虑现在修改的上述服务以返回一个Observable:

public Observable<Message> getAMessageObs() {
    return Observable.<Message>create(s -> {
        logger.info("Start: Executing slow task in Service 1");
        Util.delay(1000);
        s.onNext(new Message("data 1"));
        logger.info("End: Executing slow task in Service 1");
        s.onCompleted();
    }).subscribeOn(Schedulers.from(customObservableExecutor));
}

我可以通过在Web层结束阻塞调用来使返回Observable的所有好处无效,一个朴素的调用将是以下内容:

@RequestMapping("/getAMessageObsBlocking")
public Message getAMessageObsBlocking() {
    return service1.getAMessageObs().toBlocking().first();
}

为了使此流在Web层中异步,以下是处理此调用的更好方法,基本上是将Observable转换为Spring的DeferredResult类型:

@RequestMapping("/getAMessageObsAsync")
public DeferredResult<Message> getAMessageAsync() {
    Observable<Message> o = this.service1.getAMessageObs();
    DeferredResult<Message> deffered = new DeferredResult<>(90000);
    o.subscribe(m -> deffered.setResult(m), e -> deffered.setErrorResult(e));
    return deffered;
}

这将确保处理用户流的线程将在服务调用完成后立即返回,并且一旦可观察到的开始发出值,就将对用户响应进行反应性处理。

如果您有兴趣进一步探索, 这里是一个带有工作示例的github存储库:https://github.com/bijukunjummen/spring-web-observable。

参考文献:

Spring关于Web层中异步流的参考指南:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-async

NoBlogDefFound博客上无与伦比的Tomasz Nurkiewicz提供的有关Spring DeferredResult更多详细信息 -http://www.nurkiewicz.com/2013/03/deferredresult-asynchronous-processing.html

翻译自: https://www.javacodegeeks.com/2015/03/using-rx-java-observable-in-a-spring-mvc-flow.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值