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

标签 java spring-boot 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() 方法获取响应。

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

关于java - 如何使用 RestTemplate 将上游错误响应传递给下游服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61292703/

相关文章:

java - Spring 数据 JPA 分页发生在数据库级别或应用程序级别

java - ClassCastException:RestTemplate 返回 List<LinkedHashMap> 而不是 List<MymodelClass>

java - org.springframework.web.client.RestClientException : No HttpMessageConverter for java. util.HashMap 中出现错误

java - 将curl http请求转换为Java的错误请求

java - 在jpa hibernate中使用存储库查询sql时无限递归

java - 在 hadoop 中连接到 HDFS 时出现 EOFException

java - 无法从 java 连接到本地 mongoDB

java - java中禁用按钮时如何摆脱视觉效果

java - 直接自引用导致循环父类(super class)问题 JSON

java - 在 Spring Boot 应用程序中通过 Jersey 资源方法提供静态内容