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

如何在SpringWebFlux中整合Mono对象的结果?

何建中
2023-03-14

请查看以下使用RestTemplate的controller代码(添加注释):

@GetMapping("/{courseid}")
public Course getCourseDetails(@PathVariable Long courseid) {

    // Get Course info (ID, Name, Description) from pre-populated Array List
    CourseInfo courseInfo = getCourseInfo(courseid);
    
    // Get Price info of a course from another microservice using RESTTemplate
    Price price = restTemplate.getForObject("http://localhost:8002/price/"+courseid, Price.class);
    
    // Get enrollment info of a course from another microservice using RESTTemplate
    Enrollment enrollment = restTemplate.getForObject("http://localhost:8003/enrollment/"+courseid, Enrollment.class);
    
    //Consolidate everything in to Course object and send it as response
    return new Course(courseInfo.getCourseID(), courseInfo.getCourseName(), courseInfo.getCourseDesc(), price.getDiscountedPrice(),
            enrollment.getEnrollmentOpen());
}

现在,我正试图通过反应式编程实现同样的目标。我现在使用WebFlux中的WebClient和Mono。但是,我很困惑如何将结果结合起来?看一看下面的代码(在任何地方都使用Mono,其余代码保持不变)

@GetMapping("/{courseid}")
public Mono<Course> getCourseDetails(@PathVariable Long courseid) {

    // Get Course info (ID, Name, Description) from pre-populated Array List
    CourseInfo courseInfo = getCourseInfo(courseid);
    
    // Get Price info of a course from another microservice using RESTTemplate
    Mono<Price> price = webClient.get().uri("http://localhost:8002/price/{courseid}/",courseid).retrieve().bodyToMono(Price.class);
    
    // Get enrollment info of a course from another microservice using RESTTemplate
    Mono<Enrollment> inventory = webClient.get().uri("http://localhost:8003/enrollment/{courseid}/",courseid).retrieve().bodyToMono(Enrollment.class);
    
    //Question : How do we Consolidate everything and form a Mono<Course> object and send it as response?
    
}

问题1:我们如何整合一切,形成一个Mono对象,并将其作为响应发送出去?

问题2:“CourseInfo CourseInfo=getCourseInfo(courseid);”语句导致阻塞操作?

谢谢!

共有2个答案

刘向阳
2023-03-14

>

  • restTemplate.getForObject返回简单的对象-在您的情况下Price注册。要将它们转换为Mono,您可以简单地Mono.just(对象),然而更好的解决方案是切换到WebClient,这是Spring Reactive的默认HTTP客户端

    getCourseInfo这取决于此方法背后的逻辑。可以肯定的是,如果该方法后面有JDBC连接,那么它将被阻塞。

    使用Mono进行最终响应

    例如:

    Mono<Course> courseMono = Mono.zip(price, enrollment)
            .map(tuple -> new Course(courseInfo, tuple.getT1(), tuple.getT2()));
    

  • 曹浩淼
    2023-03-14

    答复:

    问题1:我们如何整合一切,形成一个Mono对象,并将其作为响应发送出去?

    莫诺。拉链(…)这是将两个结果结合起来所需要的。此图来自文档:

    请注意,zip如果A或1中的一个为空,将导致一个空单声道!使用switchIfEmpty/defaultIfEmpty来防止这种情况。

    因此,代码如下所示:

    @GetMapping("/{courseid}")
    public Mono<Course> getCourseDetails(@PathVariable Long courseid) {
    
        CourseInfo courseInfo = getCourseInfo(courseid);
        Mono<Price> priceMono = webClient.get().uri("http://localhost:8002/price/{courseid}/",courseid).retrieve().bodyToMono(Price.class);
        Mono<Enrollment> enrollmentMono = webClient.get().uri("http://localhost:8003/enrollment/{courseid}/",courseid).retrieve().bodyToMono(Enrollment.class);
        
        return Mono.zip(priceMono, enrollmentMono).map(t -> new Course(courseInfo.getCourseID(), courseInfo.getCourseName(), courseInfo.getCourseDesc(), t.getT1().getDiscountedPrice(),
                t.getT2().getEnrollmentOpen()));
        
    }
    
    

    现在回答:

    问题2:“CourseInfo CourseInfo=getCourseInfo(courseid);”语句导致阻塞操作?

    既然你提到了从预填充的数组列表中获取课程信息(ID,名称,描述),如果它只是一个包含课程信息的内存数组,那么它不是阻塞的。

    但是(正如@mslowiak也提到的),如果getCourseInfo包含涉及查询数据库的逻辑,请确保您没有使用阻塞JDBC驱动程序。如果是这样,那么使用Webflux和Reactor就没有意义了。如果是这种情况,请使用Spring R2DBC。

     类似资料:
    • 我有以下代码: 现在我使我的存储库成为反应性的。我的问题是如何使缓存存储现在单声道和通量。 我遇到了以下Mono和Flux缓存,但这只是为了查找,因为我也是反应式编程的初学者。

    • 我有一节这样的课 并从外部API向webclient获取数据 我想把数据转换成下面这样。 这是我的尝试 我的方法似乎是同步的。

    • 好吧,所以我有下面的方法,但我试图摆脱使用。块(),因此尝试实现Mono,但得到错误< code >所需的类型:List 原始代码 我尝试以非阻塞方式重构使用 Mono

    • 如何将flux 转换为mono 对象?

    • 情况如下:我有两个MongoDB文档:用户和复制。 在检查用户是否有复制条目(文档)的基础上,我想在MongoDB中添加另一个实体。 目前我正在使用SpringWebFlux和SpringReactiveMongo。请参阅下面的代码。 我的问题如下:如何使用Mono的结果来验证正确的Mono是否存在,并基于该保存解析器文档。基本上结合两个单声道流的结果,以便执行另一个文档的保存,并以非阻塞的方式执

    • 关于混合对象 可以混合对象以创建形状,并在两个对象之间平均分布形状。也可以在两个开放路径之间进行混合,在对象之间创建平滑的过渡;或组合颜色和对象的混合,在特定对象形状中创建颜色过渡。 注意:混合对象与将混合模式或透明度应用于对象不同。有关混合模式和透明度的信息,请参阅关于混合模式。 在对象之间创建了混合之后,就会将混合对象作为一个对象看待。如果您移动了其中一个原始对象,或编辑了原始对象的锚点,则混