当返回ResponseEntity和Http错误时,RestTemplate.postForObject返回Null

问题描述 投票:0回答:2

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

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

PersonResponse类包含一个“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)时,后端仍然会返回一个PersonResponse,但只有“status”字段填充了错误信息,这就是后端返回给我的响应:

 backend code:

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

但我下面的调用返回了一个null响应,虽然它应该给我一个带有错误信息的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
java spring-boot http httpresponse resttemplate
2个回答
1
投票

请阅读以下内容:

默认情况下,如果出现RestTemplate错误,exceptions将抛出其中一个HTTP

HttpClientErrorException

- 在HTTP状态4xx的情况下

HttpServerErrorException

- 在HTTP状态5xx的情况下

UnknownHttpStatusCodeException

- 在未知的HTTP状态的情况下

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

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

此外,您使用response HTTP 500状态接收的(INTERNAL SERVER ERROR)RestTemplate将不会使用POJO映射/反序列化,因为它不再是成功(HTTP 200)响应,即使后端将errorCode和消息包装在状态中。

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

现在根据您的需要,我想从您的原始帖子,即使在4xx或5xx状态,您想要返回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并在Handler中集中,如果您从后端接收4xx或5xx,您将决定如何从您的客户端做出响应。最后,这一切都取决于你如何设计你的系统,因为你说你无法控制后端,那么你必须根据后端响应在你的客户端实现。

希望这可以帮助。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.