1

请查看使用 RestTemplate 的控制器(添加评论)的以下代码:

@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());
}

现在我正在尝试使用反应式编程来实现相同的目标。我现在使用来自 Web-Flux 的 WebClient 和 Mono。但是,我很困惑如何组合结果?看看下面的代码(只是使用 Mono Everywhere。其余代码保持不变)

@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);”是否 导致阻塞操作?

谢谢!

4

2 回答 2

1
  1. restTemplate.getForObject返回简单对象 - 在您的情况下PriceEnrollment. 您可以简单地将它们转换为 Mono Mono.just(object),但更好的解决方案是切换到Webclient,它是 Spring Reactive 的默认 HTTP 客户端

  2. getCourseInfo这取决于这种方法背后的逻辑是什么。确定该方法后面是否存在 JDBC 连接,它是阻塞的。

  3. 要与您做出最终回应,Mono<Course>您应该考虑zip 运算符,这将帮助您。

例如:

Mono<Course> courseMono = Mono.zip(price, enrollment)
        .map(tuple -> new Course(courseInfo, tuple.getT1(), tuple.getT2()));
于 2020-07-24T13:54:29.437 回答
1

回答:

问题 1:我们如何合并所有内容并形成 Mono 对象并将其作为响应发送?

Mono.zip(..)是您需要结合这两个结果的内容。该图来自文档

压缩文件

请注意,如果 A 或 1 之一为空,zip则将导致Mono为空!使用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);”是否 导致阻塞操作?

既然你提到了Get Course info (ID, Name, Description) from pre-populated Array List如果它只是一个包含课程信息的内存数组,那么它不是阻塞的

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

于 2020-07-25T07:21:06.427 回答