我们如何在 Java 中进行异步 REST api 调用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56250191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 01:15:47  来源:igfitidea点击:

How can we make asynchronous REST api call in Java?

javaspringrestresttemplateasyncresttemplate

提问by user10937286

I am using Spring RestTemplate and want to make a call to another service that doesn't return any response body. So, I don't want to wait for the response. So, it's just fire and forget, and continue with the remaining code. I am thinking of creating a new Thread to do this but really not sure what's the correct approach.

我正在使用 Spring RestTemplate 并想调用另一个不返回任何响应正文的服务。所以,我不想等待回应。所以,这只是一劳永逸,然后继续剩下的代码。我正在考虑创建一个新线程来执行此操作,但真的不确定什么是正确的方法。

采纳答案by Gal Naor

The correct approach is to execute the async with a callback (using DeferredResult, like this (assuming we have a class someClassthat we want to retrieve from the API:

正确的方法是使用回调执行异步(使用DeferredResult,像这样(假设我们有一个someClass要从 API 检索的类:

@GetMapping(path = "/testingAsync")
public DeferredResult<String> value() throws ExecutionException, InterruptedException, TimeoutException {
   AsyncRestTemplate restTemplate = new AsyncRestTemplate();
   String baseUrl = "http://someUrl/blabla";
   HttpHeaders requestHeaders = new HttpHeaders();
   requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
   String value = "";

   HttpEntity entity = new HttpEntity("parameters", requestHeaders);
   final DeferredResult<String> result = new DeferredResult<>();
   ListenableFuture<ResponseEntity<someClass>> futureEntity = restTemplate.getForEntity(baseUrl, someClass.class);

   futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<someClass>>() {
      @Override
      public void onSuccess(ResponseEntity<someClass> result) {
         System.out.println(result.getBody().getName());
         result.setResult(result.getBody().getName());
      }

      @Override
      public void onFailure(Throwable ex) {
         result.setErrorResult(ex.getMessage());
      }
  });

  return result;
}

回答by Turac

If you use Java 11, java support asynchronous HTTP Client. Asynchronous client using CompletableFuturein the back. You can see javadoc.

如果您使用 Java 11,则 Java 支持异步 HTTP 客户端。异步客户端在后面使用CompletableFuture。你可以看到javadoc

HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://openjdk.java.net/"))
            .timeout(Duration.ofMinutes(1))
            .header("Content-Type", "application/json")
            .POST(BodyPublishers.ofFile(Paths.get("file.json")))
            .build();

    client.sendAsync(request, BodyHandlers.ofString())
            .thenApply(response -> { System.out.println(response.statusCode());
                return response; } )
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println);

If you are using a lower version than java11, this documentmay give a idea(see page 30) or can read similar questionin stackoverflow.

如果您使用的版本低于 java11,本文档可能会提供一个想法(参见第 30 页)或可以在 stackoverflow 中阅读类似的问题

回答by Ashish Girdhar

There are many ways you can use to fire the request using the AsyncRestTemplate

您可以通过多种方式使用 AsyncRestTemplate 触发请求

The simplest way is just like restTemplate and call exchange method:

最简单的方法就像restTemplate和调用交换方法:

AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
JSONObject json = new JSONObject();
json.put("firstName","testUser");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<String>(json.toString(), headers);

Class<String> responseType = String.class;
ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.exchange("https://xxxxx.com/", HttpMethod.POST, requestEntity,responseType );

// If you want for the result then you can use 
 try {
        //waits for the result
        ResponseEntity<String> entity = future.get();
        //prints body source code for the given URL
        log.info(entity.getBody());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
}

If we want to play with the failure (fallback scenario) or success in that case we can use the below code :

如果我们想在这种情况下尝试失败(回退场景)或成功,我们可以使用以下代码:

AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
JSONObject json = new JSONObject();
json.put("firstName","testUser");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<String>(json.toString(), headers);

 //final DeferredResult<String> result = new DeferredResult<>();
 ListenableFuture<ResponseEntity<String>> future = 
 asyncRestTemplate.postForEntity("https://xxxx.com", requestEntity, String.class);

  future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {

 @Override
 public void onFailure(Throwable ex) {
// insert into the table or log or some other decision
 log.info(ex.getMessage());
 }

        @Override
        public void onSuccess(ResponseEntity<String> result) {
            log.info(result.getBody());
            log.info("Sucess");
        }
    });