java - 处理 Java RestClient 中的异常

标签 java rest

我需要编写一个由多个返回特定对象的应用程序使用的 RestClient。 如果出现错误请求(400),我想向调用者应用程序提供消息错误和状态代码的建议。 我想知道抛出带有代码和消息属性的托管异常是否是一个好的行为,以便从调用者代码中正确捕获。 像这样的事情:

RestClient.java

ClientResponse response;
try {
    response = client.resource(requestURI).queryParams(queryParams)
            .type(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON)
            .post(ClientResponse.class, richiesta);

    boolean output =  response.getStatus() == Response.Status.NO_CONTENT.getStatusCode();

    if (!output && response.getStatus() == Response.Status.BAD_REQUEST)
        throw new RestClientRuntimeException(response.getStatus, response.getEntity(String.class));

} catch (ClientHandlerException e) {
    throw new RestClientRuntimeException(e);
} catch (UniformInterfaceException e) {
    throw new RestClientRuntimeException(e);
}

调用者应用程序

try 
{

    boolean output = restClient.method()

} catch (RestClientRuntimeException e) {

    // read exception status and message entity

}

这是一个好的做法吗?

最佳答案

你的问题有几个方面。让我们分别考虑它们:

我应该将 http 错误代码转换为异常吗?

是的,您应该将错误代码转换为异常。异常(exception)是好的(当然如果使用正确的话)。他们将幸福之路与特殊情况分开。如果您不使用异常而是返回代码,则调用者需要检查该返回代码。如果你调用多个方法,你会得到一些令人讨厌的级联 if:

if (service1.method1() == NO_ERROR) {
    if (service2.method2() = NO_ERROR) {
        if (service3.method2() = NO_ERROR) {
            ...
        } else {
            ...
        }
    } else {
        ...
    }
} else {
    ...
}

此外,如果您有多个层(并且几乎肯定有),则需要在每个级别再次执行此操作。这里的异常(exception)要好得多。他们让你先编码(并阅读!)美好而干净的快乐之路,然后 您可以担心 catch block 中的异常。这更容易编写和阅读。

我应该使用检查异常吗?

这可能会变得非常宗教化。有些人认为检查异常是个好主意,有些人则认为它们是邪恶的。我不想在这里详细讨论这个问题。只是这样:您想强制您的调用者考虑该特定异常吗?调用者是否总是或至少在绝大多数情况下有一种方法来处理该异常?

如果您得出的结论是调用者除了记录异常并自行失败之外无法执行任何操作,则应避免使用已检查的异常。这使得调用者代码更加简洁。无意义的 try..catch block 没有任何用处,它们只是为了让编译器满意。

说到休息:如果是 500,很可能没有机会恢复。如果您收到 405 错误,则很可能存在错误,而且也无法恢复。如果您收到 409 冲突,并包含一些有关如何解决冲突的特殊信息,可能有一个很好的方法来处理该问题(取决于您的要求)。在这种情况下,您可以考虑检查异常。

我应该将响应代码存储在异常中吗?

当您使用通用 RestClientRuntimeException 并让调用者查询响应代码时,那么您的调用者显然与此 REST 调用耦合。如果您正在编写可以查询任意 REST API 的通用 REST 客户端,则可以这样做。在这种情况下没有问题。

但是您已经在使用通用库(我猜是 Jersey)。那么,将通用 API 包装在通用 API 周围有什么意义呢?可能有一些原因(例如评估一些内部使用的 header 参数),但您应该考虑这是否合理。

也许您想编写一个特定于应用程序的 REST 客户端,即反序列化特定于应用程序的表示类 (DTO) 的客户端。在这种情况下,您不应使用通用异常,而应使用特定于应用程序的异常。如果您使用特定于应用程序的异常,您的调用者不会与 REST 调用耦合。也许将来出现了一种很酷的新技术,你需要改变你的客户。如果您使用通用异常并让调用者评估响应代码,则调用者也需要进行更改。但如果使用特定于应用程序的异常,这个接口(interface)会更加稳定。调用者甚至不需要知道 REST 之类的东西存在。当您分离关注点时,这使得调用者代码更简单且更易于维护。

我应该将休息客户端放入 jar 中吗?

我知道你没有问过这个问题。但也许你应该这样做。向任意客户端提供具有 Jersey 依赖项的其余客户端 jar(在我看来,您就是这样做的)乍一看不错,但可能会让您陷入依赖项的真正麻烦。如果您不相信,我可以详细解释这一点,但让我们在一个单独的问题中讨论这一点。

关于java - 处理 Java RestClient 中的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39913615/

相关文章:

java - .NET 应用程序的部署与 Java Web 应用程序的部署相比如何?

java - 使用 Spring HATEOAS 嵌套嵌入到 HAL 中

api - Azure "Easy Tables"Rest API主体

java - 从每个 Rest Assured 测试中获取 "CURL"操作,未通过测试时在控制台打印

azure - 用于访问 Azure 上的公共(public) RESTServer 应用程序的请求 OAuth2 参数

java - Selenium Java API 为什么 driver.findElement(By.tagName ("title")).getText() 总是返回空

java - 从 Android 中的 ArrayAdapter 获取资源

java - ArrayList,对象覆盖

Java 基础正则表达式 : get value of both placeholders

javascript - 使用 ORM(如 ActiveRecord)为 Web API 定义模型时, 'Type Tables'(如 BOOK_TYPE 表)的重要性