RestTemplate.postForObject Returns 返回ResponseEntity和Http错误时为空

RestTemplate.postForObject Returns Null When ResponseEntity and Http Error Are Returned

我调用后端服务取回 PersonResponse 对象:

PersonResponse response = restTemplate.postForObject(url, request, PersonResponse.class);

PersonResponse class 包含一个 "status" 字段来指示是否从后端成功检索到一个人的信息:

 public class PersonResponse {
    private String name;
    private String address;
    private ResponseStatus status;
     ......
 }

 public class ResponseStatus {
    private String errorCode;
    private String errorMessage;
     ......
 }

因此,当成功检索响应时 (http 200),我能够取回 PersonResponse 类型的响应。但是,当出现错误(400 或 500)时,后端仍然 return 给我一个 PersonResponse,但只有 "status" 字段填充了错误信息,后端 return 就是这样给我回复:

 backend code:

 PersonResponse errResp = .....; // set the status field with error info
 return new ResponseEntity<PersonResponse>(errResp, HttpStatus.INTERNAL_SERVER_ERROR); 

但是我下面的调用 return 给我一个空响应,尽管它应该给我一个带有错误信息的 PersonResponse。谁能告诉我这是为什么?

try {
PersonResponse response = restTemplate.postForObject(url, request, PersonResponse.class);
} catch (HttpStatusCodeException se) {
  log.debug(se.getResponseBodyAsString()); 
  // I was able to see the error information stored in PersonResponse in the log
}        
return response;  // always null when 500 error is thrown by the backend

您应该处理 HttpClientErrorException 并尝试将您的服务 return 语句更改为 ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errResp)

请阅读以下内容:

默认情况下,RestTemplate 将在 HTTP 错误的情况下抛出其中之一 exceptions

HttpClientErrorException

– 如果是 HTTP 状态 4xx

HttpServerErrorException

– 如果是 HTTP 状态 5xx

UnknownHttpStatusCodeException

– 在 未知 HTTP 状态

的情况下

所有这些exceptions都是RestClientResponseException的扩展。

现在,由于您的后端正在响应 5xx(在您的情况下为 500),因此对于您的客户 RestTemplate 它是 HttpServerErrorException.

此外,您收到的 response 状态为 HTTP 500 (INTERNAL SERVER ERROR)RestTemplate 不会 map/de-serialize 返回 POJO,因为它不是更多的是成功 (HTTP 200) 响应,即使后端将错误代码和消息包装在状态中。

因此,在你的情况下总是null

现在根据您的需要,我认为您的原始 post,即使在 4xx 或 5xx 状态下您也想要 return ResponseEntity。您可以为相应的 catch 块实现,例如:

try {
PersonResponse response = restTemplate.postForObject(url, request, PersonResponse.class);
} catch (HttpStatusCodeException se) {
  log.debug(se.getResponseBodyAsString()); 
  // I was able to see the error information stored in PersonResponse in the log
// Here you have to implement to map the error with PersonResponse 
 ResponseStatus  errorStatus = new ResponseStatus();
 errorStatus.setErrorCode(HTTP500);
 errorStatus.setErrorMessage(YOURMESSAGEFROMERROR);
 PersonResponse  responseObject = new PersonResponse();
 responseObject.setResponseStatus(errorStatus);
 return new ResponseEntity<PersonResponse>(responseObject,HTTPStatus.200Or500); // you can design as you need 200 or 500
 } catch (HttpClientErrorException ex){
   //same way for HTTP 4xx 
}

此外,还有其他方法,例如 this:在您使用 SpringExceptionHandler 的地方,如果您从后端收到 4xx 或 5xx,则在 Handler 中集中决定如何从客户端响应。 最后这一切都取决于你如何设计你的系统,因为你说你无法控制后端然后你必须根据后端响应在你的客户端实现东西。

希望对您有所帮助。