Подтвердить что ты не робот

Как извлечь код статуса HTTP из вызова RestTemplate на URL?

Я использую RestTemplate, чтобы сделать HTTP-вызов нашей службе, который возвращает простой ответ JSON. Мне не нужно разбирать этот JSON вообще. Мне просто нужно вернуть все, что я получаю от этой службы.

Итак, я сопоставляю это с String.class и возвращаю фактический JSON response как строку.

RestTemplate restTemplate = new RestTemplate();

String response = restTemplate.getForObject(url, String.class);

return response;

Теперь вопрос -

Я пытаюсь извлечь HTTP Status codes после попадания в URL. Как я могу извлечь код состояния HTTP из вышеуказанного кода? Нужно ли мне вносить какие-либо изменения в то, как я это делаю сейчас?

Обновление: -

Это то, что я пробовал, и я могу получить ответ назад и код состояния. Но всегда ли мне нужно установить HttpHeaders и Entity объект, как показано ниже, я это делаю?

    RestTemplate restTemplate = new RestTemplate();     

    //and do I need this JSON media type for my use case?
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    //set my entity
    HttpEntity<Object> entity = new HttpEntity<Object>(headers);

    ResponseEntity<String> out = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);

    System.out.println(out.getBody());
    System.out.println(out.getStatusCode());

Пара вопросов. Мне нужно иметь MediaType.APPLICATION_JSON, поскольку я просто делаю вызов url, который возвращает ответ, он может возвращать JSON или XML или простую строку.

4b9b3361

Ответ 1

Используйте методы RestTemplate#exchange(..), которые возвращают ResponseEntity. Это дает вам доступ к строке состояния и заголовкам (и, очевидно, к телу).

Ответ 2

Если вы не хотите оставлять прекрасную абстракцию вокруг методов RestTemplate.get/postForObject..., подобных мне, и не любите сражаться с шаблонами, необходимыми при использовании RestTemplate.exchange... (Request- and ResponseEntity, HttpHeaders и т.д.), s другой вариант для доступа к кодам HttpStatus.

Просто обведите обычный RestTemplate.get/postForObject... с помощью try/catch для org.springframework.web.client.HttpClientErrorException и org.springframework.web.client.HttpServerErrorException, как в этом примере:

try {
    return restTemplate.postForObject("http://your.url.here", "YourRequestObjectForPostBodyHere", YourResponse.class);

} catch (HttpClientErrorException | HttpServerErrorException httpClientOrServerExc) {

    if(HttpStatus.NOT_FOUND.equals(httpClientOrServerExc.getStatusCode())) {
      // your handling of "NOT FOUND" here  
      // e.g. throw new RuntimeException("Your Error Message here", httpClientOrServerExc);
    }
    else {
      // your handling of other errors here
}

Здесь org.springframework.web.client.HttpServerErrorException добавляется для ошибок с 50x.

Теперь вы можете просто реагировать на все требуемые коды состояния - кроме соответствующего, который соответствует вашему HTTP-методу - например, GET и 200, который не будет обрабатываться как исключение, так как это соответствующий. Но это должно быть прямо, если вы реализуете/потребляете сервисы RESTful:)

Ответ 3

private RestTemplate restTemplate = new RestTemplate();

ResponseEntity<String> response = restTemplate.exchange(url,HttpMethod.GET, requestEntity,String.class);

ответ содержит "body", "headers" и "statusCode"

чтобы получить statusCode: response.getStatusCode();

Ответ 4

Могут быть несколько более хитрые случаи использования, которые могут быть у кого-то (как и я). Рассмотрим следующее:

Поддержка объекта страницы, чтобы использовать его с RestTemplate и ParameterizedTypeReference:

RestPageResponse

import java.util.ArrayList;
import java.util.List;

import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

public class RestResponsePage<T> extends PageImpl<T>{

  private static final long serialVersionUID = 3248189030448292002L;

  public RestResponsePage(List<T> content, Pageable pageable, long total) {
    super(content, pageable, total);
  }

  public RestResponsePage(List<T> content) {
    super(content);
  }

  public RestResponsePage() {
    super(new ArrayList<T>());
  }

} 

Использование ParameterizedTypeReference приведет к следующему:

ParameterizedTypeReference<RestResponsePage<MyObject>> responseType = 
new ParameterizedTypeReference<RestResponsePage<MyObject>>() {};
HttpEntity<RestResponsePage<MyObject>> response = restTemplate.exchange(oauthUrl, HttpMethod.GET, entity, responseType);

Вызов #exchange:

HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            HttpEntity<?> entity = new HttpEntity<>(headers);

response = restTemplate.exchange("localhost:8080/example", HttpMethod.GET, entity, responseType);

Теперь вот "сложная" часть.

Попытка обмена вызовами getStatusCode будет невозможна, потому что компилятор, к сожалению, не будет знать о "предполагаемом" типе response.

Это объясняется тем, что генерические средства реализуются с помощью стирания типа, которое удаляет всю информацию о родовых типах во время компиляции (подробнее - источник)

((ResponseEntity<RestResponsePage<MyObject>>) response).getStatusCode()

В этом случае вам нужно явно передать переменную в требуемый класс, чтобы получить statusCode (и/или другие атрибуты)!

Ответ 5

exchange (...) работает, но если вы хотите меньше кода, вы можете использовать

org.springframework.boot.test.web.client.TestRestTemplate.getForEntity(...)

который возвращает сущность, содержащую StatusCode. Измените ваш пример кода на это:

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
HttpStatus statusCode = response.getStatusCode();

Чтобы проверить это, вы можете использовать этот фрагмент из моего модульного теста:

ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertResponseHeaderIsCorrect(response, HttpStatus.OK);

/**
 * Test the basics of the response, non-null, status expected, etc...
 */
private void assertResponseHeaderIsCorrect(ResponseEntity<String> response, HttpStatus expectedStatus) {
    assertThat(response).isNotNull();
    assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8);
    assertThat(response.getStatusCode()).isEqualTo(expectedStatus);
}

Ответ 6

Достаточно HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode(); этот большой объем кода. HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode();

Ответ 7

Если вы хотите получить все HTTPS-состояния из RestTemplate, включая 4XX и 5XX, вам нужно будет предоставить ResponseErrorHandler для restTemplate, так как обработчик по умолчанию выдаст исключение в случае 4XX или 5XX

Мы могли бы сделать что-то подобное:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
    @Override
    public boolean hasError(HttpStatus statusCode) {
        return false;
    }
});

ResponseEntity<YourResponse> responseEntity =
    restTemplate.getForEntity("http://your.url.here", YourResponse.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.XXXX);