当前位置: 首页 > 知识库问答 >
问题:

Webflux链式多单声道

汪皓
2023-03-14

我是反应编程(spring webflux)的新手,我想知道如何最好地处理这个用例。我有一个返回Mono的反应服务调用(getAccount),我想将它与另一个返回Mono 的服务调用getBooks和一个执行某种转换并返回类似Mono 的最终同步调用转换链接起来,当getAccount或getBooks返回空时,我如何以Mono 的形式链接并返回转换后的数据?这里是我试图做的一个简化版本,作为一个例子。

这里有一些假服务

 public static Mono<String> getAccount(String name){
        return Mono.just(name);
    }
    public static Mono<Set<Book> getBooks(String title){
        return Mono.just(Sets.newHashSet(new Book(title + "One", "Author One"),
            new Book(title +"Two", "Author Two"),
            new Book(title + "Three", "Author Three")));

    }
    public static LibraryBook transform (Book a){
        return new LibraryBook(a.getTitle(), a.getAuthorName(), "someUniqueId");
    }

我想获得一个给定用户的帐户,找到他/她借阅的所有书籍,并转换这些书籍,以Mono 的形式返回值,同时在适当的地方记录警告

这是我的开始

public Mono<Set<LibraryBook>> getBorrowedBooks(String userId) {
     return getAccount(userId)
            .flatMap(account ->  getBooks(account))
            .log()
            .map(books -> books.stream().map(book -> transform(book)).collect(Collectors.toSet()))
          
}

然而,我不确定混合反应和流是不是一件坏事,它只是看起来不对。

共有1个答案

柴衡
2023-03-14

更新:

由于您不能修改getBooks方法,您可以按照以下方式构造getBorrowedBooks方法,以避免处理流。

注意-记录器和异常只是示例。您还可以以不同的方式处理空场景。

public class MyApp {

  private static final Logger LOGGER = LoggerFactory.getLogger(MyApp.class);

  public static void main(String[] args) {

    List<LibraryBook> libraryBooks = getBorrowedBooks("Abhi").collectList().block();
    libraryBooks.forEach(System.out::println);
  }

  public static Mono<String> getAccount(String name) {
    return Mono.just(name);
  }

  public static Mono<Set<Book>> getBooks(String title) {
    return Mono.just(Sets.newHashSet(new Book(title + "One", "Author One"),
        new Book(title + "Two", "Author Two"),
        new Book(title + "Three", "Author Three")));

  }

  public static LibraryBook transform(Book a) {
    return new LibraryBook(a.getTitle(), a.getAuthorName(), "someUniqueId");
  }

  public static Flux<LibraryBook> getBorrowedBooks(String userId) {
    return getAccount(userId)
        .switchIfEmpty(Mono.defer(() -> {
          LOGGER.error("No account found");
          return Mono.error(new NoAccountFoundException());
        }))
        .flatMap(account -> getBooks(account))
        .flatMapMany(Flux::fromIterable)
        .switchIfEmpty(Mono.defer(() -> {
          LOGGER.error("No books found for account");
          return Mono.error(new NoBooksFoundForGivenAccountException());
        }))
        .map(MyApp::transform);
  }

编译明智这是正确的。但从逻辑上来说,我认为这是不正确的,因为你没有考虑单声道和通量的定义。

单声道是由0..1个元素组成的流。通量是一种可以发射0..n个元素的流。

方法getBooks(顾名思义)应该为给定的标题发出1个以上的元素(这里是Book)。所以它的返回类型应该是flux而不是集合的Mono。

甚至可以从spring的反应存储库方法中获取示例:

现在,在reactive world中,移除重复项并将集合存储在hashset中的想法与对一系列元素调用distinct()同义。

因此您的getBooks方法应该如下所示:

  public static Flux<Book> getBooks(String title){

    return Flux.just(new Book(title + "One", "Author One"),
        new Book(title +"Two", "Author Two"),
        new Book(title + "Three", "Author Three"))
        .distinct();

  }

您的getBorrowedBooks方法应该如下所示:

  public Flux<LibraryBook> getBorrowedBooks(String userId) {
    return getAccount(userId)
        .flatMapMany(account -> getBooks(account))
        .log()
        .map(book -> transform(book));
  }
 类似资料:
  • 我不知道或问这个问题,除了这里,如果不是我道歉的地方。 这里有一个REST请求,它附带了一个简单的bean,其中包含一个列表等属性。对此列表进行迭代,以使用返回Mono(findOne)的响应mongo调用。但我不认为我找到了正确的方法: 在我看来,“反应性”的想法并不是必须做一个块,但我没有找到如何做,否则。 有人能帮我找到做这项任务的最佳方法吗?

  • 我正在尝试使用SpringBoot2.0和新的reactive webFlux库。我想知道如何将通过无阻塞WebClient进行的两个调用的结果返回给我的Springboot API的调用者。我的代码是: 然而,如果我这样称呼它,我得到的回应是 而不是SearchResponse对象的内容。我觉得我可能错过了一个基本的点,这是如何工作的!我的想法是,因为WebClient没有阻塞,所以我可以向we

  • 获取所有分支 遍历所有并将其添加到 返回,这是我不确定这样做是否正确的地方。但它起作用了 合并所有列表 我只是困惑,这是在我的上下文中使用的正确方式吗?或者有没有什么更好的方法来实现我正在努力做的事情?

  • 我的代码如下 因为和都可能返回错误或空单声道。我想返回类似于消息取决于哪个Mono是空的。我该怎么做? 如果我在单声道之后添加一个。zip,我不知道哪个组件是空的。。。

  • 我是Spring新来的。我在这里遇到了一个小问题“userMono不是空的”,但这部分代码正在执行“switchiffempty(Mono.just(“hello123”)”