抛出RestClientException时如何检索HTTP状态代码和响应正文?

时间:2012-09-23 15:25:50

标签: java resttemplate

RestTemplate的方法,例如postForEntity()抛出RestClientException。我想从catch块中的异常对象中提取HTTP状态代码和响应主体。我怎么能这样做?

4 个答案:

答案 0 :(得分:32)

不要抓住RestClientException,而是抓住特殊的HttpClientErrorException

以下是一个例子:

try {
    Link dataCenterLink = serviceInstance.getLink("dataCenter");
    String dataCenterUrl = dataCenterLink.getHref();
    DataCenterResource dataCenter =
        restTemplate.getForObject(dataCenterUrl, DataCenterResource.class);
    serviceInstance.setDataCenter(dataCenter);
} catch (HttpClientErrorException e) {
    HttpStatus status = e.getStatusCode();
    if (status != HttpStatus.NOT_FOUND) { throw e; }
}

HttpClientErrorException分别提供getStatusCodegetResponseBodyAsByteArray来获取状态代码和正文。

答案 1 :(得分:1)

在某些情况下,不会引发 HttpClientErrorException 。例如,以下方法 restTemplate.exchange

ResponseEntity<Employee[]> employees =  restTemplate.exchange(url, HttpMethod.GET, entity, Employee[].class);

获取http正文并将其编组为实体。如果远程资源返回一个罕见的错误,则内部编组将不起作用,并且只会抛出 RestClientException

restTemplate.setErrorHandler

在这种情况下,或者如果您想处理 restTemplate 操作中的任何错误,则可以使用 setErrorHandler 。此方法会接收带有帮助方法的基本 ResponseErrorHandler

此方法 hasError 允许我获取远程http正文文本,并帮助我检测调用的错误或远程http远程资源中的错误:

restTemplate.setErrorHandler(new ResponseErrorHandler() {

  @Override
  public boolean hasError(ClientHttpResponse arg0) throws IOException {

    System.out.println("StatusCode from remote http resource:"+arg0.getStatusCode());
    System.out.println("RawStatusCode from remote http resource:"+arg0.getRawStatusCode());
    System.out.println("StatusText from remote http resource:"+arg0.getStatusText());

    String body = new BufferedReader(new InputStreamReader(arg0.getBody()))
          .lines().collect(Collectors.joining("\n"));

    System.out.println("Error body from remote http resource:"+body);
    return false;
  }

  @Override
  public void handleError(ClientHttpResponse arg0) throws IOException {
    // do something
  }
});

您还可以手动评估正文或状态,并返回true或false,以标记是否为错误。

答案 2 :(得分:1)

改为捕获RestClientResponseException。更通用。

来自docs:常见基类,用于包含实际HTTP响应数据的异常。

答案 3 :(得分:0)

private void sendActivity(StatsActivity statsActivity) throws InterruptedException 
{
    LibraryConnectorXapiEditView libraryConnectorXapiEditView = (LibraryConnectorXapiEditView) workerBundle.getConnector();
    
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    Statement statement = libraryConnectorConverter.convertActivityToStatement(statsActivity, workerBundle);
    HttpEntity<Statement> request = new HttpEntity<>(statement, headers);
    
    try
    {
       String lrsEndPoint = libraryConnectorXapiEditView.getLrsEndPoint() + "/statements";
       ResponseEntity<String> response = restTemplate.exchange(lrsEndPoint, HttpMethod.POST, request, String.class);
       ocnCompletionEventDao.save(this.convertToOcnCompletionEvent(statsActivity, response.getBody(), response.getStatusCodeValue()));
    }
    catch (HttpClientErrorException ex)
    {
      ocnCompletionEventDao.save(this.convertToOcnCompletionEvent(statsActivity, ex.getResponseBodyAsString(), ex.getStatusCode().value()));
      checkResponse(ex, libraryConnectorXapiEditView);  
      if(failedAttempts<3) 
      { 
          sendActivity(statsActivity);
          failedAttempts++;
      }
    }   
}

private void checkResponse(HttpClientErrorException ex, LibraryConnectorXapiEditView libraryConnectorXapiEditView) throws InterruptedException 
{
    int statusCode = ex.getStatusCode().value();
    int retryAfterSeconds = retryAfter(ex.getResponseHeaders());
    
    switch (statusCode)
    {
    case 401: 
        headers = xApiAuthorizationUtils.getHeaders(libraryConnectorXapiEditView);
    case 429:
        if(retryAfterSeconds!=0)
            Thread.sleep(retryAfterSeconds);
    case 422: 
        failedAttempts=3;
    }
 }