【问题标题】:How to extract HTTP status code from the RestTemplate call to a URL?如何从对 URL 的 RestTemplate 调用中提取 HTTP 状态代码?
【发布时间】:2014-06-05 23:29:54
【问题描述】:

我正在使用RestTemplate 对我们的服务进行 HTTP 调用,该服务返回一个简单的 JSON 响应。我根本不需要解析那个 JSON。我只需要退还我从该服务中获得的任何东西。

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

RestTemplate restTemplate = new RestTemplate();

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

return response;

现在的问题是——

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

更新:-

这是我尝试过的,我也能够得到响应和状态码。但是我是否总是需要像下面这样设置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());

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

【问题讨论】:

  • 很棒的教程在这里:baeldung.com/rest-template
  • @david,发生异常时如何获取状态码,比如超时和服务错误

标签: java url http-status-codes resttemplate


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    现在是“棘手”的部分。

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

    这是因为泛型是通过类型擦除实现的,它会在编译期间删除有关泛型类型的所有信息(read more - source)

    ((ResponseEntity&lt;RestResponsePage&lt;MyObject&gt;&gt;) response).getStatusCode()

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

    【讨论】:

      【解决方案3】:

      如果您不想像我一样将 RestTemplate.get/postForObject... 方法的抽象概念抛在脑后,并且不喜欢在使用 RestTemplate.exchange...(Request-和 ResponseEntity、HttpHeaders 等)时摆弄所需的样板文件,那么可以s 访问 HttpStatus 代码的另一个选项。

      只需将常用的RestTemplate.get/postForObject...org.springframework.web.client.HttpClientErrorExceptionorg.springframework.web.client.HttpServerErrorException 的try/catch 括起来,如下例所示:

      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 方法匹配的适当状态码 - 例如 GET200,它们不会被作为异常处理,因为它是匹配的。但这应该是直截了当的,如果您正在实施/使用 RESTful 服务:)

      【讨论】:

      • 为了获取响应代码而引发异常是一个非常阴暗的解决方法......正如你在回答中所写的那样,你无法验证成功的请求200
      • 我不明白你的意思 - 不同的 HTTP 代码然后 200 由 Spring 通过异常自动表示,我不会在这里“创建”它们或其他东西。 “验证成功的请求200”是什么意思?您可以在 restTemplate.postForObject() 方法调用之后执行任何操作 - 这正是 200 状态的表示,因为所有其他状态都将(并且如前所述由 Spring 表示)作为异常。
      • @jonashackt for 1xx 和 3xx 也会例外?
      【解决方案4】:
      private RestTemplate restTemplate = new RestTemplate();
      
      ResponseEntity<String> response = restTemplate.exchange(url,HttpMethod.GET, requestEntity,String.class);
      

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

      获取状态码:response.getStatusCode();

      【讨论】:

        【解决方案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();
        

        要对其进行测试,您可以使用我的单元测试中的这个 sn-p:

        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&lt;Object&gt;) responseOfEsoft).getStatusCode();

          【讨论】:

            【解决方案7】:

            如果你想要来自 RestTemplate 的所有 HTTPStatus,包括 4XX 和 5XX,你必须为 restTemplate 提供一个 ResponseErrorHandler,因为默认处理程序会在 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);
            

            【讨论】:

              【解决方案8】:

              你可以使用这个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();
              

              【讨论】:

                【解决方案9】:

                能够通过以下方式解决此问题:
                HttpEntity&lt;Object&gt; entity = restTemplate.getForEntity(uri, Object.class);

                ResponseEntity&lt;String&gt; result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-09-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-11-21
                  • 1970-01-01
                  相关资源
                  最近更新 更多