Java 8泛型如果特定异常则重试

时间:2017-02-14 16:26:46

标签: java spring exception-handling

我发现自己编写了很多看起来像

的重试循环
    int triesRemaining = 3;

    while (triesRemaining > 0) {
        try {
            <MY FUNCTION CALL>
            LOGGER.info("success");
            break;
        } catch (Exception e) {
            if (e.getCause() instanceof SocketTimeoutException) {
                triesRemaining--;
                LOGGER.info(e.getMessage() + " trying again. Tries Remaining: " + triesRemaining);
            } else {
                LOGGER.error(e.getMessage(), e);
                return;
            }
        }
    }
    if (triesRemaining == 0) {
        LOGGER.error("Failed over too many times");
    }

我想编写一个接受Lambda的泛型函数,并且仅针对特定错误进行重试(在上述情况下为SocketTimeoutException)。我已经看到一些接受Runnable的函数很好,但它们似乎不允许限制特定的异常。

有什么建议吗?

5 个答案:

答案 0 :(得分:1)

嗯,它已经完成了。它还接受您要重试的例外列表。它还提供线性/指数重试策略。 看看https://github.com/rholder/guava-retrying

来自自述文件的一个简单示例,您可以编写并使用如下的重试程序: -

Callable<Boolean> callable = new Callable<Boolean>() {
public Boolean call() throws Exception {
    return true; // do something useful here
}};

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
    .retryIfResult(Predicates.<Boolean>isNull())
    .retryIfExceptionOfType(IOException.class)
    .retryIfRuntimeException()
    .withStopStrategy(StopStrategies.stopAfterAttempt(3))
    .build();

try {
  retryer.call(callable);
} catch (RetryException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

答案 1 :(得分:1)

查看org.springframework.retry

有一个注释@Retryable,它符合您的需要。您可以指定要重试的例外类型并配置尝试次数等...

答案 2 :(得分:0)

问题是什么让这个函数接受Runnable参数然后在<MY FUNCTION CALL>中运行?

public static void retry(Runnable r) {
      // ...
      while (triesRemaining > 0) {
        try {
            r.run();
            LOGGER.info("success");
            break;
        } 
      // ...
}

然后调用它(如果您愿意 - 使用lambda):

    retry(() -> {
        connectToServer();
        // todo what-ever-you-want
    });

答案 3 :(得分:0)

我相信您正在寻找基于纯Java的解决方案。基于假设,我会说Java 8使用功能接口,一个带有单一抽象方法的接口。我会创建一个新的 RetryCommand 类,它有一个 run 方法,它接受一个函数。

答案 4 :(得分:0)

结帐Failsafe

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(SocketTimeoutException.class)
  .withMaxRetries(3);

Failsafe.with(retryPolicy)
  .onRetry((c, f, ctx) -> log.warn("Failure #{}. Retrying.", ctx.getExecutions()))
  .onFailure(e -> LOGGER.error(e.getMessage(), e))
  .run(() -> myFunctionCall());