Java 如何从对 URL 的 RestTemplate 调用中提取 HTTP 状态代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23205213/
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-13 21:19:35  来源:igfitidea点击:

How to extract HTTP status code from the RestTemplate call to a URL?

javaurlhttp-status-codesresttemplate

提问by john

I am using RestTemplateto make an HTTP call to our service which returns a simple JSON response. I don't need to parse that JSON at all. I just need to return whatever I am getting back from that service.

我正在使用RestTemplateHTTP 调用我们的服务,它返回一个简单的 JSON 响应。我根本不需要解析那个 JSON。我只需要归还我从该服务中得到的任何东西。

So I am mapping that to String.classand returning the actual JSON responseas a string.

所以我将它映射到String.class并将实际JSON response作为字符串返回。

RestTemplate restTemplate = new RestTemplate();

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

return response;

Now the question is -

现在的问题是——

I am trying to extract HTTP Status codesafter hitting the URL. How can I extract HTTP Status code from the above code? Do I need to make any change into that in the way I doing it currently?

我试图HTTP Status codes在点击 URL 后提取。如何从上述代码中提取 HTTP 状态代码?我是否需要以目前的方式对其进行任何更改?

Update:-

更新:-

This is what I have tried and I am able to get the response back and status code as well. But do I always need to set HttpHeadersand Entityobject like below I am doing it?

这是我尝试过的,我也能够得到响应和状态代码。但是我是否总是需要像下面那样设置HttpHeadersEntity反对我正在做的事情?

    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());

Couple of question - Do I need to have MediaType.APPLICATION_JSONas I am just making a call to url which returns a response back, it can return either JSON or XML or simple string.

几个问题 - 我是否需要拥有,MediaType.APPLICATION_JSON因为我只是调用 url 返回响应,它可以返回 JSON 或 XML 或简单的字符串。

采纳答案by Sotirios Delimanolis

Use the RestTemplate#exchange(..)methods that return a ResponseEntity. This gives you access to the status line and headers (and the body obviously).

使用RestTemplate#exchange(..)返回 a的方法ResponseEntity。这使您可以访问状态行和标题(显然还有正文)。

回答by Menelaos Kotsollaris

There can be some slightly trickier use cases someone might fall in (as I did). Consider the following:

有些人可能会陷入一些稍微棘手的用例(就像我所做的那样)。考虑以下:

Supporting a Page object in order to use it with RestTemplateand ParameterizedTypeReference:

支持 Page 对象以便将其与RestTemplateParameterizedTypeReference一起使用:

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

} 

Using ParameterizedTypeReferencewill yield the following:

使用ParameterizedTypeReference将产生以下结果:

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

Calling #exchange:

调用#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);

Now here is the "tricky" part.

现在是“棘手”的部分。

Trying to call exchange's getStatusCodewill be impossible because the compiler, unfortunately, will be unaware of the "intended" type of response.

尝试调用 exchangegetStatusCode是不可能的,因为不幸的是,编译器将不知道“预期”类型的response.

That is because generics are implemented via type erasure which removes all information regarding generic types during compilation (read more - source)

那是因为泛型是通过类型擦除实现的,它在编译期间删除了有关泛型类型的所有信息(阅读更多 - 源代码)

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

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

In this case, you have to explicitly cast the variable to the desired Class to get the statusCode(and/or other attributes)!

在这种情况下,您必须显式地将变量强制转换为所需的类以获取statusCode(和/或其他属性)!

回答by jonashackt

If you don′t want to leave the nice abstraction around RestTemplate.get/postForObject...methods behind like me and dislike to fiddle around with the boilerplate stuff needed when using RestTemplate.exchange...(Request- and ResponseEntity, HttpHeaders, etc), there′s another option to gain access to the HttpStatus codes.

如果你不想像RestTemplate.get/postForObject...我一样留下围绕方法的漂亮抽象,并且不想在使用RestTemplate.exchange...(请求和响应实体、HttpHeaders 等)时摆弄所需的样板文件,还有另一个选项可以访问 HttpStatus代码。

Just surround the usual RestTemplate.get/postForObject...with a try/catch for org.springframework.web.client.HttpClientErrorExceptionand org.springframework.web.client.HttpServerErrorException, like in this example:

只需RestTemplate.get/postForObject...用 try/catch for org.springframework.web.client.HttpClientErrorExceptionand包围通常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
}

The org.springframework.web.client.HttpServerErrorExceptionis added here for the errors with a 50x.

org.springframework.web.client.HttpServerErrorException此添加了一个错误50x

Now you′re able to simple react to all the StatusCodes you want - except the appropriate one, that matches your HTTP method - like GETand 200, which won′t be handled as exception, as it is the matching one. But this should be straight forward, if you′re implementing/consuming RESTful services :)

现在你可以对所有你想要的 StatusCode 做出简单的反应——除了合适的,匹配你的 HTTP 方法——比如GETand 200,它不会作为异常处理,因为它是匹配的。但这应该是直截了当的,如果您正在实施/使用 RESTful 服务:)

回答by santosh kumar

private RestTemplate restTemplate = new RestTemplate();

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

response contains 'body', 'headers' and 'statusCode'

响应包含“body”、“headers”和“statusCode”

to get statusCode : response.getStatusCode();

获取 statusCode : response.getStatusCode();

回答by LazR

exchange(...) works but if you want less code, you can use

exchange(...) 有效,但如果你想要更少的代码,你可以使用

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

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

which returns an Entity containing StatusCode. Change your example code to this:

它返回一个包含 StatusCode 的实体。将您的示例代码更改为:

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

To test it you can use this snippet from my unit test:

要测试它,您可以使用我的单元测试中的这个片段:

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

回答by Subha Mukherjee

Putting this much of code is enough for me HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode();

放这么多代码对我来说已经足够了 HttpStatus statusCode = ((ResponseEntity<Object>) responseOfEsoft).getStatusCode();

回答by Matthieu Gabin

If you want all the HTTPStatus from a RestTemplate including 4XX and 5XX, you will have to provide an ResponseErrorHandler to the restTemplate, since the default handler will throw an exception in case of 4XX or 5XX

如果您想要来自 RestTemplate 的所有 HTTPStatus,包括 4XX 和 5XX,则必须向 restTemplate 提供 ResponseErrorHandler,因为默认处理程序将在 4XX 或 5XX 的情况下抛出异常

We could do something like that :

我们可以这样做:

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

回答by El Fadel Anas

You can use this solution

您可以使用此解决方案

RestTemplate restTemplate = new RestTemplate();

final String baseUrl = "http://www.myexampleurl.com";
URI uri = new URI(baseUrl);

ResponseEntity<String> result = restTemplate.getForEntity(uri, String.class);

//get status code
int statuCode = result.getStatusCodeValue();