1

我正在使用弹性 4j 的 TimeLimiter 来控制 RestTemplate 调用的超时请求。如果 response.getBody() 为空,我将抛出一个自定义异常,但是在 getorElseThrow 中提供了 Resilience4j 总是抛出异常。如何在这里抛出自定义异常?

Try.ofCallable(methodWhichThrowsCustomException).getOrElseThrow(throwable -> {throw new ApplicationException(HttpStatus.REQUEST_TIMEOUT,
                    ErrorConstant.ERROR_CODE_REQUEST_TIMEOUT, ErrorConstant.ERROR_MESSAGE_TIME_OUT);
        });
    }

在这里,我正在尝试抛出“methodWhichThrowsCustomException”抛出的异常,但我无法做到这一点,它只会抛出此处抛出的异常。

4

2 回答 2

1

我不知道resilience4j,但我很确定你用getOrElseThrow错了。您最可能想要的语法是:

Try.ofCallable(methodWhichThrowsCustomException())
   .getOrElseThrow(throwable -> new ApplicationException(HttpStatus.REQUEST_TIMEOUT, ErrorConstant.ERROR_CODE_REQUEST_TIMEOUT, ErrorConstant.ERROR_MESSAGE_TIME_OUT));

注意你不需要throwinside getOrElseThrow,你只需要返回新的异常来抛出,Vavr 会负责抛出它。

于 2019-07-21T05:34:11.200 回答
0

瓦弗的Try.of().getOrElseThrow()

请参阅博客Vavr One Log 03 - 安全尝试

T getOrElseThrow(供应商)

getOrElseThrow期望异常提供者作为参数。这可以是 lambda、方法引用或任何函数。其目的是将抛出的异常映射到您的自定义异常实例。例如:

Try.ofCallable(methodWhichThrowsCustomException)
    .getOrElseThrow(throwable -> new CustomerException(
        HttpStatus.REQUEST_TIMEOUT,
        ErrorConstant.ERROR_CODE_REQUEST_TIMEOUT, 
        ErrorConstant.ERROR_MESSAGE_TIME_OUT,
        throwable
    ))
}

问题

注意:我们使用throwable -> new ..内括号,仅此而已。异常实例刚刚创建(并隐式返回),我们不抛出它 - 我们将它提供给然后抛出的vavr

你通过了一个消费者。消费 lambda{ throw new ...; }立即抛出一个新的异常,而不是简单地用{ return new CustomException("Custom message", thrown); }.

也可以看看

例外情况TimeLimiter

抛出“methodWhichThrowsCustomException”抛出的异常

假设你有一个方法:

public String sayHelloWorld(boolean shouldThrow) throws CustomException {
    if (shouldThrow) throw new CustomException("Hello Exception");
    return "Hello World!";
}

你将它传递给TimeLimiter 当它执行并且它无法在时间内成功完成时,它会抛出两个异常之一

  1. 当超过时间限制时,Resilience4J 会抛出TimeoutException

当发生超时时,它会在抛出TimeoutException.

  1. 对于任何其他ExecutionException,例如当您的方法引发自定义异常时,它会找到该原因并重新引发此异常。见TimeLimiterImpl,catch-block,第 57 行

然后你应该能够抓住它:

try {
    // The blocking variant which is basically future.get(timeoutDuration, MILLISECONDS)
    String result = timeLimiter.executeFutureSupplier(
  () -> CompletableFuture.supplyAsync(() -> sayHelloWorld(true)));
    log.info(result);
} catch (Exception e) {
    log.error(e); // or print to debug, handle, etc.
}

或使用 Vavr 的Try

String result = Try.of(() -> timeLimiter.executeFutureSupplier(
  () -> CompletableFuture.supplyAsync(() -> sayHelloWorld(true))) // method forced to throw
).getOrElseThrow(throwable -> throwable); // will throw as is (without mapping to another exception)
log.info(result);

也可以看看:

使用 Resilience4j 实现超时 - 反射

于 2022-01-09T01:13:07.777 回答