引发Exception以便在API中将响应消息传播给用户的最佳实践是吗?

时间:2019-03-01 15:00:21

标签: java spring web-applications architecture microservices

我们有一个基于微服务的体系结构,该体系结构包含主应用程序服务器模块和libs模块。 在主应用服务器中,我们仅接受请求并通过REST API方法上的请求和响应对象提供响应,这些方法调用libs模块中可用的服务层。

  parent--
       ------apps
                ---server
                       ---Controller Class
       ------libs
                ---core
                       ---Service Layer
                       ---Dao Layer

要传播错误消息以便可以使用Response Object(仅在Controller类中提供)将其发送到客户端,我们在服务层中抛出自定义异常,以便可以将错误消息发送到Controller类。 这种方法的问题是,在所有情况下都将引发异常,例如,即使输入不正确或用户没有权限,我们也会引发异常,在这种情况下,我们可以仅向用户返回错误消息。

我的问题是-仅出于将错误消息从Service层传播到Controller的目的而抛出Custom异常是否正确? 如果否,那么我们如何将错误消息传播到控制器层?

服务层---

public String serviceLayerMethod(String param) throws AssetException {
    try {
        if(param==null){
        throw new CustomException;
          } else{
          return param;
        }
    } catch (CustomException e) {
        LOGGER.error(CustomExceptionEnum.PARAMNULL_EXCEPTION.getMessage(),e);
        throw new CustomException(CustomExceptionEnum.PARAMNULL_EXCEPTION.getMessage(), e);
    }
}

控制器层---

public Response restAPI(Request request) {
    try {
        response.setMessage(service.serviceLayerMethod());
        response.setSuccess(true);
    } catch (CustomException e) {
        response.setMessage(e.getMessage());
        response.setSuccess(false);
    }
    return response
}

4 个答案:

答案 0 :(得分:2)

我看不到有任何问题,但是使用Spring在Rest API上为您做的更好。

在Spring上,您可以使用@RestControllerAdvice@ExceptionHandler来捕获任何异常并为用户返回一个不错的消息。喜欢:

@Slf4j
@RestControllerAdvice
public class ErrorHandlerController {

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<ApiErrorResponse> handleApiException(CustomException ex, Locale locale) {
        log.error("Custom error catch with the code {}", ex.getErrorCode(), ex);
        ApiErrorResponse error = new ApiErrorResponse(ex, locale);
        return new ResponseEntity<>(error, ex.getHttpStatus());
    }
}

答案 1 :(得分:1)

正如内维尔指出的那样;这是一个值得商topic的话题,没有什么是对与错。

我的观点是API应该独立于UI。因此,如果异常引发异常,则可以将其抛出。并让客户端处理该异常或决定如何处理该异常。一些客户可能想显示一条优美的用户友好消息;其他客户端可能想要实际的消息(例如,如果另一个算法正在调用此API)。

答案 2 :(得分:0)

我认为记录该错误并仅将HTTP错误显示为该错误是有意义的,例如BAD_REQUEST或INTERNAL_SERVER_ERROR ...

答案 3 :(得分:0)

这是complex and subtle topic-可能基于意见。

首先,避免使用异常来传达应用程序逻辑。您的示例并不暗示您正在执行此操作,但通常使用自定义异常来传达应用程序或域逻辑,并且在try / catch块中对其进行处理很难读取,难以测试且难以发展。例如,如果由于客户超出了信用额度(业务规则)而导致购买失败,那么我将避免使用自定义例外来管理该实例。

第二,尝试使用内置异常,而不是创建自己的异常。 Java有几个内置的参数验证实例。复制它们不会增加任何价值。仅在找不到内置Java异常时才创建自​​定义异常。

第三,如果可以的话,尝试在控制器层中处理应用程序异常-将所有内容下推到服务层中会使该层变得更加复杂且难以测试。

最后,重点关注如何将错误传达给客户端-常见的模式是使用HTTP错误代码。最终,您可能最终将自定义异常转换为“ HTTP:500”代码,并且希望您的客户端应用程序能够以一致的方式推理这些异常。