繁体   English   中英

如何使用 RestTemplate 将上游错误响应传递给下游服务

[英]How to pass upstream error response to downstream service using RestTemplate

我无法处理从一个微服务到另一个微服务的错误响应。 假设服务 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() 方法获得响应。

但是,如果您没有公开 REST 服务,我认为您可能会返回状态码为 200 的应用程序逻辑错误。为所有具有以下字段的响应创建一个基本 class:errorCode、errorMessage、errorCause(例如)。 通过您的 REST 响应类扩展它。 如果一切正常 - 返回带有 errorCode 0 的常规响应。但是如果您在处理请求时遇到错误,请返回带有一些 errorCode(不是 0)的响应,并填写 errorMessage 和 errorCause 字段。 这不是“最佳实践”,但有时可能对您来说很全面。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM