使用Spring Boot处理REST Web服务异常

3
我正在使用spring/spring-boot开发REST客户端库和REST服务器。该库将作为其他应用程序的依赖项。
最佳处理错误的方式是什么?我考虑在服务器端处理错误,例如使用ControllerAdvice将错误映射到错误DTO类。在客户端(使用RestTemplate)中,我想要:
1. 如果出现错误(响应4xx/5xx),则反序列化错误DTO并抛出已检查异常(需要在使用库的应用程序中处理)。 2. 在正常情况下,只需反序列化预期的DTO对象并返回。
我试图使用ResponseErrorHandler实现这一点,并提出了两个解决方案,但它们并不完全令我满意,因此我想听取意见或得到更好的建议:
idea 1:
    public List<SomeDTO> list() throws MyException {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
    HttpEntity<String> request = new HttpEntity<>(headers);
    ResponseEntity<String> response = restTemplate.exchange("endpoint/getAll", HttpMethod.GET, request, String.class);
    String responseBody = response.getBody();
    try {
        if (MyResponseErrorHandler.isError(response.getStatusCode())) {
            ErrorInfo error = objectMapper.readValue(responseBody, ErrorInfo.class);
            throw new MyException();
        } else {
            List<SomeDTO> SomeDTOs = Arrays.asList(objectMapper.readValue(responseBody));
            return SomeDTOs;
        }
    } catch (IOException e) {
        throw new MyException();
    }
}

但是每个方法看起来都需要很多样板代码。

想法2A

在ResponseErrorHandler中抛出自定义异常,需要是Runtime或IOException,但在IOException的情况下会被ResourceAccessException包装。在客户端方法中,可以捕获异常并重新抛出另一个异常。但是某个地方(在catch块中?)需要将错误响应映射到自定义异常(也可能会抛出IOException)。

想法2B 不要使用ResponseErrorHandler,在catch块中捕获HttpClientErrorException并使用getResponseBodyAsString从中获取响应正文,并将其映射到自定义错误类型(捕获IOException)

有什么想法吗?提前感谢。


使用ControllerAdvice有什么问题吗?它有助于(至少对我来说:P)将实际逻辑和异常处理解耦。 - ansh
1个回答

0

在REST API中返回错误的标准方式是使用HTTP代码。

但在这种情况下,您正在开发客户端库,因此可以选择自己的设计。

我也遇到过这种情况。尽管其他人只会使用客户端库。因此,REST API对他们来说是隐藏的。虽然我通过ControllerAdvice处理了已知的异常,并始终返回一个对象,例如 int code; String message; Object payload; 显然,HTTP代码始终为200(OK)。

将响应代码作为ENUM具有以下好处:可以获取所有已处理的错误,包括特定消息以创建客户端异常,我还知道有效请求的负载对象的特定类别。因此,在客户端中,这些返回代码(ENUM)使得从客户端抛出异常更容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接