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

时间:2019-05-22 05:57:43

标签: java spring rest resttemplate asyncresttemplate

我正在使用Spring RestTemplate,并且想调用另一个不返回任何响应主体的服务。因此,我不想等待响应。因此,这只是一劳永逸而已,然后继续其余的代码。我正在考虑创建一个新的线程来执行此操作,但实际上不确定什么是正确的方法。

3 个答案:

答案 0 :(得分:1)

正确的方法是使用回调执行异步(使用DeferredResult,如下所示(假设我们有一个要从API检索的类someClass

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

答案 1 :(得分:1)

如果使用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);

如果您使用的版本低于java11,则this document可能会给出一个主意(请参阅第30页),或者可以在stackoverflow中阅读similar question

答案 2 :(得分:0)

您可以使用多种方法使用AsyncRestTemplate触发请求

最简单的方法就像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();
}

在这种情况下,如果我们要尝试失败(后备方案)或成功,则可以使用以下代码:

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");
        }
    });