Spring Resttemplate异常处理

vai*_*hav 88 rest spring exception-handling resttemplate

以下是代码段; 基本上,当错误代码不是200时,我试图传播异常.

ResponseEntity<Object> response = restTemplate.exchange(url.toString().replace("{version}", version),
                    HttpMethod.POST, entity, Object.class);
            if(response.getStatusCode().value()!= 200){
                logger.debug("Encountered Error while Calling API");
                throw new ApplicationException();
            }
Run Code Online (Sandbox Code Playgroud)

但是,如果来自服务器的500响应,我将获得异常

org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
Run Code Online (Sandbox Code Playgroud)

我真的需要在try中包装其余的模板交换方法吗?那么代码的目的是什么?

car*_*ret 103

您希望创建一个实现的类,ResponseErrorHandler然后使用它的实例来设置其余模板的错误处理:

public class MyErrorHandler implements ResponseErrorHandler {
  @Override
  public void handleError(ClientHttpResponse response) throws IOException {
    // your error handling here
  }

  @Override
  public boolean hasError(ClientHttpResponse response) throws IOException {
     ...
  }
}

[...]

public static void main(String args[]) {
  RestTemplate restTemplate = new RestTemplate();
  restTemplate.setErrorHandler(new MyErrorHandler());
}
Run Code Online (Sandbox Code Playgroud)

另外,Spring有类DefaultResponseErrorHandler,你可以扩展而不是实现接口,以防你只想覆盖handleError方法.

public class MyErrorHandler extends DefaultResponseErrorHandler {
  @Override
  public void handleError(ClientHttpResponse response) throws IOException {
    // your error handling here
  }
}
Run Code Online (Sandbox Code Playgroud)

看看它的源代码,了解Spring如何处理HTTP错误.

  • 我有 1 个 RestTemplate 实例,可用于不同的调用。我需要以不同的方式处理来自不同调用的错误 - 显然没有办法用全局处理程序来做到这一点 - 我需要为每个请求提供一个处理程序。 (7认同)
  • 使用这个错误处理程序,我总是得到一个`ResourceAccessException`,因为`RestTemplate.doExecute`捕获`IOException`s并抛出`ResourceAccessException`.我究竟做错了什么? (3认同)

mek*_*azu 34

你应该抓住一个HttpStatusCodeException例外:

try {
    restTemplate.exchange(...);
} catch (HttpStatusCodeException exception) {
    int statusCode = exception.getStatusCode().value();
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • IMO响应应始终带有适当的状态代码,否则代码的目的是什么. (30认同)
  • "很贵"?比起拨打HTTP电话费用更高? (7认同)
  • 我不确定是否理解@vaibhav异议:捕获HttpStatusCodeException不是用于错误的代码,而是因为在许多情况下总是抛出异常,因此永远不能执行if(code == value). (4认同)
  • Java 中的异常代价非常高。对于偶尔的意外原因(因此得名)是可以的,但除此之外,您应该寻找其他解决方案。 (3认同)
  • @RaffaelBecharaRameh - HttpStatusCodeException .getResponseBodyAsString()或HttpStatusCodeException.getResponseBodyAsByteArray(). (2认同)

aus*_*rlo 29

Spring巧妙地将http错误代码视为异常,并假设您的异常处理代码具有处理错误的上下文.要使交换功能正常运行,请执行以下操作:

    try {
        return restTemplate.exchange(url, httpMethod, httpEntity, String.class);
    } catch(HttpStatusCodeException e) {
        return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders())
                .body(e.getResponseBodyAsString());
    }
Run Code Online (Sandbox Code Playgroud)

这将返回响应的所有预期结果.

  • “聪明地”——需要引用 (4认同)
  • 这很有帮助,谢谢,尽管我不同意假设事情是明智之举 (3认同)
  • 您需要使用与默认 SDK 不同的 HttpClient,以获取错误的响应正文 (2认同)
  • 聪明又名 https://en.wikipedia.org/wiki/Kludge,而不是 KISS http://principles-wiki.net/principles:keep_it_simple_stupid。一些开发人员不喜欢使用异常处理作为流程控制的方法。 (2认同)

Inv*_*tor 18

另一种解决方案是本文结尾处“ enlian”描述的解决方案:http ://springinpractice.com/2013/10/07/handling-json-error-object-responses-with-springs-resttemplate

try{
     restTemplate.exchange(...)
} catch(HttpStatusCodeException e){
     String errorpayload = e.getResponseBodyAsString();
     //do whatever you want
} catch(RestClientException e){
     //no response payload, tell the user sth else 
}
Run Code Online (Sandbox Code Playgroud)

  • 您需要使用与默认SDK不同的HttpClient来获取错误的响应正文(例如apache commons HttpClient) (2认同)

Sia*_*ter 11

这些或其他教程都对我没有帮助。RestTemplate简直就是废话。我在写这篇文章是为了让其他人不要在这个可怕的事情上浪费时间。我调用restTemplate.exchange并获取400状态代码。该行还会引发异常,但这不是HttpStatusCodeException,而是ResourceAccessException。我试过交换对象和字符串。我试过包括ResponseErrorHandler,这是完全没有用的。

这也不是我第一次也无法使用RestTemplate做我想做的事情,而且我甚至很长时间都没有使用它。不要浪费时间。

例如,您可以使用:

Apache HttpClient:https : //mvnrepository.com/artifact/org.apache.httpcomponents/httpclient

或OkHttp3:https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp


Per*_*osh 9

Spring从非常大的HTTP状态代码列表中抽象出您。那就是例外的想法。看一下org.springframework.web.client.RestClientException层次结构:

在处理http响应时,有一堆类可以映射最常见的情况。http代码列表确实很大,您不需要编写代码来处理每种情况。但是例如,请看一下HttpClientErrorException子层次结构。您只有一个例外来映射任何4xx类型的错误。如果您需要深入,那么可以。但是仅捕获HttpClientErrorException,就可以处理将错误数据提供给服务的任何情况。

DefaultResponseErrorHandler非常简单可靠。如果响应状态代码不是2xx系列,则它对hasError方法返回true。

  • 嘿伙计,我用过 Eclipse。只需按 control+shift+T 打开类型搜索器,然后输入 RestClientException。双击结果中的 RestClientException,Eclipse 将为您打开该类。然后,将鼠标光标放在类名称上(其中显示“public class RestClientException...”,然后按 control+T。您将看到该层次结构。 (2认同)

Vai*_*rma 6

一个非常简单的解决方案可以是:

try {
     requestEntity = RequestEntity
     .get(new URI("user String"));
    
    return restTemplate.exchange(requestEntity, String.class);
} catch (RestClientResponseException e) {
        return ResponseEntity.status(e.getRawStatusCode()).body(e.getResponseBodyAsString());
}
Run Code Online (Sandbox Code Playgroud)


Sai*_*pta 5

我已处理如下:

try {
  response = restTemplate.postForEntity(requestUrl, new HttpEntity<>(requestBody, headers), String.class);
} catch (HttpStatusCodeException ex) {
  response = new ResponseEntity<String>(ex.getResponseBodyAsString(), ex.getResponseHeaders(), ex.getStatusCode());
}
Run Code Online (Sandbox Code Playgroud)