如何结合 Mono 和 Flux 作为参数来创建新的 Mono?

Posted

技术标签:

【中文标题】如何结合 Mono 和 Flux 作为参数来创建新的 Mono?【英文标题】:How to combine Mono and Flux as parameters to create new Mono? 【发布时间】:2020-01-02 15:37:11 【问题描述】:

我的 REST 控制器方法应该返回 Mono,它必须由 2 个并行请求构建到另一个 Web 服务并处理它们的响应,其中一个请求返回 Mono,另一个请求返回 Flux

如何将 Mono 和 Flux 的响应结合起来处理?

型号:

@Document
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClassModel 

    @Id
    private String id;
    private String roomNr;
    private String className;
    private String teacherId;
    private List<String> studentIds;

    public void addStudentId(String studentId) 
        studentIds.add(studentId);
    


控制器:

public Mono<ClassModel> addRandomClassFull() 
    return Mono.zip(
        //request teacher microservice and return Mono - single teacher
        reactiveNetClient.addRandomTeacher(),
        //request students microservice and return Flux - list of students
        reactiveNetClient.addRandomStudents(10),
        (teacher, students) -> 
            ClassModel classModel = new ClassModel();
            classModel.setRoomNr("24B");
            classModel.setClassName(faker.educator().course());
            classModel.setTeacherId(teacher.getId());
            students.forEach(student -> classModel.addStudentId(student.getId());
            return classModel;
        ).flatMap(classRepository::save);

显然,控制器是错误的: 1) Mono.zip() 需要 2 个或更多 Mono,我有 Mono 和 Flux - 如何组合它们? 2) 也不确定:students.forEach(student -&gt; classModel.addStudentId(student.getId());是正确的方法吗?

有什么建议吗?

【问题讨论】:

【参考方案1】:
    您可以将方法addRandomStudents() 更改为返回Mono&lt;List&lt;Student&gt;&gt;

    您可以在Flux&lt;Student&gt; 上使用collectList(),它会返回然后Mono&lt;List&lt;Student&gt;&gt;,然后在addStudents() 中会将Student 对象转换为id。

    public Mono<ClassModel> addRandomClassFull() 
        return Mono.zip(
            reactiveNetClient.addRandomTeacher(),
            reactiveNetClient.addRandomStudents(10).collectList(),
            (teacher, students) -> 
                 ClassModel classModel = new ClassModel();
                 classModel.setRoomNr("24B");
                 classModel.setClassName(faker.educator().course());
                 classModel.setTeacherId(teacher.getId());
                 classModel.addStudents(students);
            return classModel;
        ).flatMap(classRepository::save);
    
    

【讨论】:

以上是关于如何结合 Mono 和 Flux 作为参数来创建新的 Mono?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用返回 Mono 的生成包装调用创建 Flux

如何从返回 Mono 的 Stream 创建 Flux? [复制]

从 Mono 的列表中创建 Flux 的正确方法

Spring 5 WebFlux Mono 和 Flux

Spring Webflux(Mono/Flux) 与 AOP 在拦截时触发 REST 调用并使用 Mono/Flux

Spring WebFlux,单元测试 Mono 和 Flux