【问题标题】:Returning multiple Monos in Spring Webflux在 Spring Webflux 中返回多个 Mono
【发布时间】:2018-09-21 18:35:39
【问题描述】:

我正在尝试使用 SpringBoot 2.0 和新的响应式 webFlux 库。我想知道如何将通过无阻塞 WebClient 进行的两次调用的结果返回给我的 Springboot API 的调用者。我的代码是:

@RequestMapping("/search")
public CombinedResults perfomSearch(@RequestParam final String searchTerm) {
    Mono<SearchResponse> fasMono = searchService.getSearchResults(searchTerm, "fh");
    Mono<SearchResponse> esMono = searchService.getSearchResults(searchTerm, "es");
    CombinedResults combinedResults = new CombinedResults(fasMono, esMono);
    return combinedResults;

}

CombinedResult 对象只是一个 POJO:

public class CombinedResults {

private Mono<SearchResponse> fasSearchResponse;

private Mono<SearchResponse> esSearchResponse;

public CombinedResults(final Mono<SearchResponse> fasSearchResponse, final Mono<SearchResponse> esSearchResponse) {
    this.fasSearchResponse = fasSearchResponse;
    this.esSearchResponse = esSearchResponse;
}

public Mono<SearchResponse> getFasSearchResponse() {
    return fasSearchResponse;
}

public void setFasSearchResponse(final Mono<SearchResponse> fasSearchResponse) {
    this.fasSearchResponse = fasSearchResponse;
}

public Mono<SearchResponse> getEsSearchResponse() {
    return esSearchResponse;
}

public void setEsSearchResponse(final Mono<SearchResponse> esSearchResponse) {
    this.esSearchResponse = esSearchResponse;
}

但是,如果我称之为,我得到的回应是

{
  "fasSearchResponse": {
    "scanAvailable": true
  },
  "esSearchResponse": {
    "scanAvailable": true
  }
}

而不是 SearchResponse 对象的内容。我觉得我可能错过了它应该如何工作的一个基本点!我的想法是,因为 WebClient 没有阻塞,我可以触发对 Web 服务的两个调用,然后将它们组合起来而不需要可完成的期货等?

【问题讨论】:

    标签: spring reactive-programming spring-webflux


    【解决方案1】:

    Spring WebFlux 不支持嵌套的响应式类型。 你应该有这样的东西:

    Mono<SearchResponse> fasMono = searchService.getSearchResults(searchTerm, "fh");
    Mono<SearchResponse> esMono = searchService.getSearchResults(searchTerm, "es");
    Mono<CombinedResults> results = fasMono.zipWith(esMono, 
        (fas, es) -> {return new CombinedResults(fas, es);});
    

    【讨论】:

    • 这似乎给了我相同的输出
    • 您是否将 combineresults 类也更改为不包含反应类型?
    • IMO,这是对这个问题的更好回答
    【解决方案2】:

    我认为您应该返回一个对象的 Mono,该对象表示此操作所响应的模型。假设 CombinedResults 是您的模型。这个类应该是这样的:

    public class CombinedResults {
    
        private SearchResponse fasSearchResponse;
    
        private SearchResponse esSearchResponse;
    
        public CombinedResults(final SearchResponse fasSearchResponse, final SearchResponse esSearchResponse) {
            this.fasSearchResponse = fasSearchResponse;
            this.esSearchResponse = esSearchResponse;
        }
    
        //... getters AND/OR setters
    }
    

    并且,在您的控制器上,您可以执行以下操作:

    @RequestMapping("/search")
    public Mono<CombinedResults> perfomSearch(@RequestParam final String searchTerm) {
        Mono<SearchResponse> fasMono = searchService.getSearchResults(searchTerm, "fh");
        Mono<SearchResponse> esMono = searchService.getSearchResults(searchTerm, "es");
        Mono<CombinedResults> combinedResults = 
            fasMono
              .flatMap(fh -> esMono.map(es -> new CombinedResults(fh, es)));
        return combinedResults;
    }
    

    这样,您将返回一个 Mono 对象,其中包含您想要的响应。当两个 Mono 发出项目时,fasMono.flatMapesMono.map 的操作链构建 CombinedResults。这种组合在尝试将两个 Mono 合并为一个时相当常见。我认为您也可以使用zip 运算符加入 Monos。 所有这些都与 WebClient 无关。如果你的getSearchResults 只执行异步非阻塞操作,那么一切都是异步非阻塞的。

    【讨论】:

      猜你喜欢
      • 2021-05-08
      • 2019-12-14
      • 2021-11-03
      • 2018-12-19
      • 2020-03-22
      • 2021-03-25
      • 2020-03-20
      • 2020-10-05
      • 2018-12-12
      相关资源
      最近更新 更多