Java RestClient中异常的处理

Java RestClient中异常的处理,java,rest,Java,Rest,我需要编写一个RestClient,由几个返回特定对象的应用程序使用。 在错误请求(400)的情况下,我想通知调用方应用程序消息错误和状态代码。 我想知道,为了从调用方代码中正确捕获,抛出带有代码和消息属性的托管异常是否是一种好行为。 大概是这样的: RestClient.java ClientResponse response; try { response = client.resource(requestURI).queryParams(queryParams)

我需要编写一个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

}

这是一个好的做法吗?

我想,至少400个状态代码有自定义异常是一个好的做法,因为这意味着发送了格式错误的数据


与抛出未检查的异常并捕获它们相比,检查的异常更合适。

我认为至少400个状态代码有自定义异常是一个好的做法,因为这意味着发送了格式错误的数据


与抛出未检查的异常并捕获它们不同,检查的异常更合适。

因为您的成功响应是JSON,所以我也将错误响应建模为JSON

例如,考虑以下JSON从POJO类序列化为代码> Error Meava.java < /C> >具有相应字段。

{
  "statusCode": 400,
  "errorMessage": "Bad Request",
  "errorDetails": "<details here>"
}
{
“状态代码”:400,
“错误消息”:“错误请求”,
“错误详细信息”:”
}

因为它是HTTP,所以最好基于HTTP状态代码来传递错误代码<代码>错误消息和
错误详细信息
在状态代码成功的情况下可以为空。

由于您的成功响应是JSON,我也会将错误响应建模为JSON

例如,考虑以下JSON从POJO类序列化为代码> Error Meava.java < /C> >具有相应字段。

{
  "statusCode": 400,
  "errorMessage": "Bad Request",
  "errorDetails": "<details here>"
}
{
“状态代码”:400,
“错误消息”:“错误请求”,
“错误详细信息”:”
}
因为它是HTTP,所以最好基于HTTP状态代码来传递错误代码<代码>错误消息和
错误详细信息
在状态代码成功的情况下可以为空。

为什么不检查

除了
400
之外,还可能发生其他错误。如果测试状态代码族,则可以捕获所有状态代码:

switch (response.getStatusInfo().getFamily()) {

case CLIENT_ERROR:
    // It's a client error
    // You can throw an exception
    break;

case SERVER_ERROR:
    // It's a server error
    // You can throw an exception
    break;

default:
    break;
}
你为什么不检查一下房间

除了
400
之外,还可能发生其他错误。如果测试状态代码族,则可以捕获所有状态代码:

switch (response.getStatusInfo().getFamily()) {

case CLIENT_ERROR:
    // It's a client error
    // You can throw an exception
    break;

case SERVER_ERROR:
    // It's a server error
    // You can throw an exception
    break;

default:
    break;
}

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

我应该将http错误代码转换为异常吗? 是的,您应该将错误代码转换为异常。异常很好(当然,如果使用正确的话)。他们将快乐之路与例外情况区分开来。如果您不使用异常,而是使用返回码,则调用者需要检查该返回码。如果你调用几个方法,你会得到一些令人讨厌的连锁反应:

if (service1.method1() == NO_ERROR) {
    if (service2.method2() = NO_ERROR) {
        if (service3.method2() = NO_ERROR) {
            ...
        } else {
            ...
        }
    } else {
        ...
    }
} else {
    ...
}
此外,如果您有多个层(几乎可以肯定您有),那么您需要在每个级别再次执行此操作。例外情况在这里要好得多。他们让你先编写(并阅读!)美好而干净的快乐之路 您可以担心catch块中的异常。这样写起来更容易,读起来也更容易

我应该使用选中的异常吗? 这可能会变得很宗教化。有些人认为检查异常是个好主意,有些人认为它们是邪恶的。我不想在这里详细讨论这个问题。只是:你想强迫你的呼叫者考虑这个特殊的异常吗?调用方是否总是或至少在绝大多数情况下都有处理该异常的方法

如果得出的结论是调用方只能记录异常并自行失败,则应避免使用选中的异常。这使得调用方代码更加清晰。毫无意义的try..catch块只是为了让编译器满意而存在,这是没有用的

说到休息:在500美元的情况下,很可能没有恢复的机会。如果你得到一个405,你很可能有一个错误,也没有办法恢复。如果您遇到一个409冲突,其中包含一些关于如何解决冲突的特殊信息,那么可能有一个很好的方法来处理它(取决于您的需求)。在这种情况下,您可以考虑检查异常。

我应该将响应代码存储在异常中吗? 当您使用generic
RestClientRuntimeException
s并让调用者查询响应代码时,调用者显然与这是一个REST调用相耦合。如果您正在编写一个可以查询任意RESTAPI的通用REST客户机,那么就可以这样做。在这种情况下没问题

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

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

我应该把一个rest客户端放进一个jar吗? 我知道你没有问过这个问题。但也许你应该这样做。向任意客户机提供一个带有Jersey依赖项的rest客户机jar(在我看来,您就是这么做的)一开始看起来不错,但可能会让您在依赖项方面遇到真正的麻烦。如果您不相信,我可以详细解释,但让我们在单独的问题中讨论。

您的问题