How to use Spring WebClient to make multiple calls simultaneously?

前端 未结 4 2109
囚心锁ツ
囚心锁ツ 2021-01-01 22:30

I want to execute 3 calls simultaneously and process the results once they\'re all done.

I know this can be achieved using AsyncRestTemplate as it is mentioned here

相关标签:
4条回答
  • 2021-01-01 23:08

    You can use Spring reactive client WebClient to send parallel requests. In this example,

    public Mono<UserInfo> getUserInfo(User user) {
            Mono<UserInfo> userInfoMono = getUserInfo(user.getId());
            Mono<OrgInfo> organizationInfoMono = getOrgInfo(user.getOrgId());
    
            return Mono.zip(userInfoMono, organizationInfoMono).map(tuple -> {
                UserInfo userInfo = tuple.getT1();
                userInfo.setOrganization(tuple.getT2());
                return userInfo;
            });
        }
    

    Here:

    • getUserInfo makes an HTTP call to get user info from another service and returns Mono
    • getOrgInfo method makes HTTP call to get organization info from another service and returns Mono
    • Mono.zip() waits all the results from all monos and merges into a new mono and returns it.

    Then, call getOrgUserInfo().block() to get the final result.

    0 讨论(0)
  • 2021-01-01 23:09

    You can make HTTP calls concurrently using simple RestTemplate and ExecutorService:

    RestTemplate restTemplate = new RestTemplate();
    ExecutorService executorService = Executors.newCachedThreadPool();
    
    Future<String> firstCallFuture = executorService.submit(() -> restTemplate.getForObject("http://first-call-example.com", String.class));
    Future<String> secondCallFuture = executorService.submit(() -> restTemplate.getForObject("http://second-call-example.com", String.class));
    
    String firstResponse = firstCallFuture.get();
    String secondResponse = secondCallFuture.get();
    
    executorService.shutdown();
    

    Or

    Future<String> firstCallFuture = CompletableFuture.supplyAsync(() -> restTemplate.getForObject("http://first-call-example.com", String.class));
    Future<String> secondCallFuture = CompletableFuture.supplyAsync(() -> restTemplate.getForObject("http://second-call-example.com", String.class));
    
    String firstResponse = firstCallFuture.get();
    String secondResponse = secondCallFuture.get();
    
    0 讨论(0)
  • 2021-01-01 23:19

    Assuming a WebClient wrapper (like in reference doc):

    @Service
    public class MyService {
    
        private final WebClient webClient;
    
        public MyService(WebClient.Builder webClientBuilder) {
            this.webClient = webClientBuilder.baseUrl("http://example.org").build();
        }
    
        public Mono<Details> someRestCall(String name) {
            return this.webClient.get().url("/{name}/details", name)
                            .retrieve().bodyToMono(Details.class);
        }
    
    }
    

    ..., you could invoke it asynchronously via:

    // ... 
      @Autowired
      MyService myService
      // ...
    
       Mono<Details> foo = myService.someRestCall("foo");
       Mono<Details> bar = myService.someRestCall("bar");
       Mono<Details> baz = myService.someRestCall("baz");
    
       // ..and use the results (thx to: [2] & [3]!):
    
       // Subscribes sequentially:
    
       // System.out.println("=== Flux.concat(foo, bar, baz) ===");
       // Flux.concat(foo, bar, baz).subscribe(System.out::print);
    
       // System.out.println("\n=== combine the value of foo then bar then baz ===");
       // foo.concatWith(bar).concatWith(baz).subscribe(System.out::print);
    
       // ----------------------------------------------------------------------
       // Subscribe eagerly (& simultaneously):
       System.out.println("\n=== Flux.merge(foo, bar, baz) ===");
       Flux.merge(foo, bar, baz).subscribe(System.out::print);
    

    [2] [3]

    Thanks, Welcome & Kind Regards,

    0 讨论(0)
  • 2021-01-01 23:21

    Another way:

    public Mono<Boolean> areVersionsOK(){
            final Mono<Boolean> isPCFVersionOK = getPCFInfo2();
            final Mono<Boolean> isBlueMixVersionOK = getBluemixInfo2();
    
            return isPCFVersionOK.mergeWith(isBlueMixVersionOK)
                .filter(aBoolean -> {
                    return aBoolean;
                })
                .collectList().map(booleans -> {
                    return booleans.size() == 2;
            });
    
        }
    
    0 讨论(0)
提交回复
热议问题