我无法处理从一个微服务到另一个微服务的错误响应。 假设服务A调用服务B。 B返回:
{
"timestamp": "2020-04-18T13:02:30.543+0000",
"status": 404,
"error": "Not Found",
"message": "Cannot find product with productId = 1",
"path": "/products/quantity/1"
}
作为ResponseEntity
中的正文。
我必须在 A 中获取相同的响应消息、状态和错误。
我正在使用 RestTemplate
从 A 调用 B。
我试过了
public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return (clientHttpResponse.getStatusCode().series() == CLIENT_ERROR ||
clientHttpResponse.getStatusCode().series() == SERVER_ERROR
);
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
if(clientHttpResponse.getStatusCode().series() == CLIENT_ERROR) {
HttpStatus httpStatus = clientHttpResponse.getStatusCode();
}
else if(clientHttpResponse.getStatusCode().series() == SERVER_ERROR) {
throw new RecordNotFoundException("Record Not found");
}
}
但在这里我只能获取 ResponseCode
而不是包含错误和消息的整个 ResponseBody
。
最佳答案
您的错误处理程序应如下所示:
public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return (clientHttpResponse.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
|| clientHttpResponse.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR);
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
HttpStatus statusCode = clientHttpResponse.getStatusCode();
switch (statusCode.series()) {
// handle client errors. Throw HttpClientErrorException
// ex.getResponseBodyAsString();
case CLIENT_ERROR:
HttpClientErrorException ex = new HttpClientErrorException(statusCode,
clientHttpResponse.getStatusText(), clientHttpResponse.getHeaders(),
this.getResponseBody(clientHttpResponse), this.getCharset(clientHttpResponse));
throw ex;
case SERVER_ERROR:
// handle server errors, may be the same as client errors, by throwing
// HttpServerErrorException
break;
default:
// default behavior for other errors
throw new RestClientException("Some Exception message");
}
}
private Charset getCharset(ClientHttpResponse response) {
HttpHeaders headers = response.getHeaders();
MediaType contentType = headers.getContentType();
return contentType != null ? contentType.getCharset() : null;
}
private byte[] getResponseBody(ClientHttpResponse response) {
byte[] result = new byte[0];
try {
// this is org.springframework.util.FileCopyUtils class
result = FileCopyUtils.copyToByteArray(response.getBody());
} catch (IOException var3) {
// Handle I/O exception
}
return result;
}
}
然后捕获异常并通过 getResponseBodyAsString() 方法获取响应。
但是,如果您没有公共(public) REST 服务,我认为您可能会返回状态代码为 200 的应用程序逻辑错误。为所有具有以下字段的响应创建一个基类:errorCode、errorMessage、errorCause(例如)。通过 REST 响应类扩展它。如果一切正常 - 返回带有 errorCode 0 的常规响应。但是,如果在处理请求时遇到错误,则返回带有一些 errorCode(而不是 0)的响应,并填写 errorMessage 和 errorCause 字段。这不是“最佳实践”,但有时可能对您来说很全面。
关于java - 如何使用 RestTemplate 将上游错误响应传递给下游服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61292703/