【问题标题】:Throw BadRequestException(ResponseEntity) vs Catch Error, return ResponseEntity(HTTPStatus.BadRequest) ReST API抛出 BadRequestException(ResponseEntity) vs Catch Error,返回 ResponseEntity(HTTPStatus.BadRequest) ReST API
【发布时间】:2020-01-27 04:53:01
【问题描述】:

我正在重构一些代码,这些代码比下面的示例更大规模。 'main' 类中充斥着这些 try/catch 块,并掩盖了代码在做什么。

我没有使用 Spring,而是使用 JaxRs 来处理异常。这将是服务或控制器的 ReST 条目,但我们也在此处执行我们的 doa 流程(我知道,但它就是这样)。所以我们需要返回一个带有所需信息的 ResponseEntity。

public restVerifyName(userId) {
    String name;
    try {
        string name = nameProvider.getName(userId)
    } catch (exception A) {
        return new errorResponseBuilder(errorCode, errorMessage, status);
    } catch (exception B) {
        return new errorResponseBuilder(errorCode, errorMessage, status);
    }

    if (name == null) {
      return new errorResponseBuilder(errorCode, errorMessage, status);
     }

    try {
        nameAuthenticator.verifyName(name)
    } catch (Exception B) {
        return new errorResponseBuilder(errorCode, errorMessage, status);
    }
    Return Response.Ok().entity(name);
}

private errorResponseBuilder(errorCode, errorMessage, status) {
    ErrorResponse errorResponse = errorResponseBuilder(errorCode, errorMessage)
    return new Response.status(status).entity(errorResponse);
}

因此,我想将这些 try/catch 提取到私有方法中,并使其更加自我记录。我的替换大致是:

public restVerifyName() {
    String name = getName();
    if (!nameIsVerfied(name)  {
         return new errorResponseBuilder(errorCode, errorMessage);
    }
    Return Response.Ok().entity(name);
}

private String getName() {
    String name;
    try {
        name = nameProvider.getName()
    } catch (exception A) {
        return new errorResponseBuilder(errorCode, errorMessage);
    } catch (exception B) {
        return new errorResponseBuilderConflict(errorCode, errorMessage);
    }

    if (name == null) {
     return new errorResponseBuilderConflict(errorCode, errorMessage);
    }
    return name;
}

private boolean verifyName(name) {
    try {
        return nameAuthenticator.verifyName(name)
    } catch (Exception B) {
        return new errorResponseBuilderBadRequest(errorCode, errorMessage);
    }
    return false;
}


private errorResponseBuilderBadRequest(errorCode, errorMessage) {
    ErrorResponse errorResponse = errorResponseBuilder(errorCode, errorMessage)
    ResponseEntity response = Response.status(status).entity(errorResponse)
    throw new BadRequestException(response)
}

private errorResponseBuilderConflict(errorCode, errorMessage) {
    ErrorResponse errorResponse = errorResponseBuilder(errorCode, errorMessage)
    ResponseEntity response = Response.status(status).entity(errorResponse)
    throw new ConfictException(response)
}

返回的响应在两个站中完全相同。

无论任何逻辑错误/格式等,哪种通用方法是最佳实践?通过响应抛出异常,或返回响应(在此示例重构目标的上下文中)

这是一个更大的规模,有更多的尝试/捕获,所以我觉得从“主”类中删除混乱更具可读性。是否使用 responseEntities 引发异常并让 JaxRs 处理它?

谢谢

【问题讨论】:

  • 这是一个广泛的问题。如果这些异常是“您的”自定义异常,您可以考虑将它们设为未经检查的异常,如果您真的必须以某种方式处理它们,我会考虑使用 Scala 或 Java 的 vavr 库中已知的更现代的方法 - 尝试容器保存结果或异常。
  • @jaroslawj 很抱歉。目标是返回一些 Http 响应,无论是 2xx 还是 4xx。因此,如果任何时候出现问题,只需将其退出并返回响应。我想尝试隐藏一些尝试容器,如果我在第二个示例周围放置另一个容器,感觉就像我为了捕捉而捕捉?

标签: java api exception java-8 jax-rs


【解决方案1】:

一般的方法是抛出带有必要嵌入细节的异常。

然后有一个全局异常处理程序将异常转换为响应。

对于 Jax-RS,您可以使用 ExceptionMapper 来捕获异常。

private String getName() {
    String name;
    //try {
        name = nameProvider.getName()
    // Only catch if exception is a checked exception or you need to transform the exception to another type with embedded detail
    // Runtime exception should generally not need to be caught here
    //} catch (exception A) {
    //    return new errorResponseBuilder(errorCode, errorMessage);
    //} catch (exception B) {
    //    return new errorResponseBuilderConflict(errorCode, errorMessage);
    //}

    if (name == null) {
       throw new ACustomErrorExceptionForThisKind(name);
    }
    return name;
}

public class ACustomErrorExceptionForThisKindMapper implements ExceptionMapper<E extends Throwable> {
   public Response toResponse(ACustomErrorExceptionForThisKind e) {
        ....
   }
}

【讨论】:

    猜你喜欢
    • 2020-05-23
    • 2018-09-15
    • 1970-01-01
    • 2022-01-06
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-03
    • 2020-05-24
    相关资源
    最近更新 更多