反应式 Spring WebClient 调用

Posted

技术标签:

【中文标题】反应式 Spring WebClient 调用【英文标题】:Reactive Spring WebClient calls 【发布时间】:2020-04-29 16:21:29 【问题描述】:

我正在尝试了解 WebFlux,但在使用 Webclient 调用时遇到了一些问题。我没有看到 这一行 System.out.println("customerId = " + customerId);执行它似乎没有调用端点。 但是如果我使用 .subscribe(customer -> ); 订阅 webclient然后我可以看到这一行 System.out.println("customerId = " + customerId);作品 在端点侧。我不明白为什么我必须订阅 Mono 通话,还是必须订阅?谢谢

@GetMapping("/customer/customerId")
@ResponseStatus(HttpStatus.ACCEPTED)
public Mono<Void> getCustomer(@PathVariable("customerId") int customerId) 
     WebClient webClient = WebClient.builder().baseUrl("http://localhost:8080").build();

 webClient.get()
  .uri("/client/customer/customerId",customerId)
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Customer.class);//here do I have to subscribe to actually activate to call?

 return null;



@GET
@Path("/customer/customerId")
@Produces(MediaType.APPLICATION_JSON)
public Customer getCustomer(@PathParam("customerId") int customerId) throws InterruptedException 
    System.out.println("customerId = " + customerId);  // I do not see the call comes thru if I dont subscribe to flux call.
    return new Customer(customerId,"custName");
 

【问题讨论】:

是的,您必须订阅。这是响应式编程的一个基本原则:订阅是一切的触发因素。在您订阅之前什么都不会发生。 projectreactor.io/docs/core/release/reference/… 但是为什么你从一个应该返回 Mono 的方法中返回 null 呢?为什么 getCustomer 方法会返回 Mono?它不应该得到客户吗?如果你真的想返回一个 Mono,那么你就不会订阅。 Spring 将为您订阅您返回的 Mono。 JB 尼泽,你是对的。返回 Void 是没有意义的。这只是一个不太关心返回类型的示例。不过感谢您的指出。 如果你通过webclient返回结果Mono,那么你不需要显式订阅。 【参考方案1】:

如果您想从 WebClient 返回响应式类型,则必须从控制器方法中返回它,例如:

@GetMapping("/customer/customerId")
@ResponseStatus(HttpStatus.ACCEPTED)
public Mono<Customer> getCustomer(@PathVariable("customerId") int customerId) 
     WebClient webClient = WebClient.builder().baseUrl("http://localhost:8080").build();

 return webClient.get()
  .uri("/client/customer/customerId",customerId)
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Customer.class);

您还可以从端点返回 Customer 并阻止并等待 WebClient 的结果,然后离开反应式生态系统,例如:

@GetMapping("/customer/customerId")
@ResponseStatus(HttpStatus.ACCEPTED)
public Customer getCustomer(@PathVariable("customerId") int customerId) 
     WebClient webClient = WebClient.builder().baseUrl("http://localhost:8080").build();

 return webClient.get()
  .uri("/client/customer/customerId",customerId)
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Customer.class)
  .block()

如果您正在查看 Spring 的 WebClient 的一般介绍,请查看 this tutorial

【讨论】:

以上是关于反应式 Spring WebClient 调用的主要内容,如果未能解决你的问题,请参考以下文章