spring - 如何在使用 Spring WebClient 时捕获 IOException?

标签 spring exception spring-webflux

我正在开发一个项目,我们正在从 RestTemplate 迁移到 WebClient

WebClient 是这样实现的:

try {
    ...
    return webClient
        .get()
        .uri(someUri)
        .retrieve()
        .toEntity(SomeBusinessClass.class).block()
} catch(WebClientException e) {
    // do some stuff
    // want to catch IOExceptions here as well
}

在重构代码的同时,我还必须重构测试,我遇到了一个测试,在该测试中我们基本上抛出一个 ConnectException 以查看我们的内部代码是否根据我们的需要捕获它们。使用 RestTemplate 的异常类,我们能够像这样定义异常:

ResourceAccessException exc = new ResourceAccessException("I/O error on GET request", new ConnectException("Connection refused: connect"))

我尝试对 WebClient 提供的异常类 WebClientException 做同样的事情,但这是一个抽象类,唯一继承自它的类是 WebClientResponseException 并且不提供允许执行相同操作的构造函数。所以我唯一的选择是使用RuntimeException:

RuntimeException exc = new RuntimeException("I/O error on GET request", new ConnectException("Connection refused: connect"))

但由于我不想重写我们的内部代码以捕获 RuntimeException 级别但 WebClientException 级别的异常,这不是一个选项吗?我想知道怎么做?

我试图在 Spring 文档中找到如何在使用 WebClient 时处理 IOException 但找不到任何东西。

这里的方法是什么?

最佳答案

最好 的方法几乎肯定是在 react 流本身中处理所有错误。服务器响应错误通常最好通过使用 exchange() 而不是 retrieve() 来处理,然后手动处理响应,以及底层的 IOException通过使用 onErrorResume()onErrorReturn() 等可用于此目的的 react 运算符。

但是,您提到您正在从阻塞代码迁移,所以我知道实际上可能(还)不会出现这种情况。如果你想坚持捕捉异常:

But since I don't want to rewrite our internal code to catch exceptions on RuntimeException level but on WebClientException level, is that not an option and I'm wondering how to do that?

想要在 WebClientException 的保护下捕获所有 传输错误不是一个明智的选择。正如您所说,出于显而易见的原因,两者都不仅仅是捕获 RuntimeException

简化它,WebClientException 意思是“我连接到 URL 并毫无问题地向它发送内容,但它告诉我离开”(即它生成错误代码而不是 200响应。)

这可能是因为 404(未找到资源)、500(服务器错误)、418(您正在尝试连接到茶壶,而不是服务器)等。

另一方面,

IOException 表示“甚至无法与此 URL 建立连接”。这可能是因为连接被主动拒绝、域名无法解析、SSL 证书过期等。

这两者并不相似,这样对待它们会很奇怪和令人困惑。

如果你想在同一个 block 中处理它们,那很好 - 天真地你可以这样做:

catch(WebClientException|IOException e) {
    // do some stuff
}

...但您当然不能,因为 IOException 已被选中。 (Java 中的 react 流不会抛出已检查的异常,每个已检查的异常都会映射到一个 RuntimeException。)

但是,您可以将所有 IOException 映射到 UncheckedIOException:

return webClient
    .get()
    .uri(someUri)
    .retrieve()
    .toEntity(SomeBusinessClass.class)
    .onErrorMap(IOException.class, UncheckedIOException::new)
    .block()

...然后要么执行 catch(WebClientException|UncheckedIOException ex),要么在单独的 catch block 中处理它们。

这当然不是从 react 性思维方式处理异常的“好”方法,但如果您的目标是以尽可能少的更改进行迁移,这可能就是您所追求的。

关于spring - 如何在使用 Spring WebClient 时捕获 IOException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61926295/

相关文章:

spring-webflux - Spring WEBLUX中阻止读取5000 MILLISECONDS的超时

java - Crudrepository/以只读方式将其他表中的单个字段连接到实体

java - 在后端处理 PUT http 请求中的可选字段的最佳方法是什么

java - 部署到 websphere 时在 hibernate 5 上使用 JPA 2.0

java - MongoDB:java.lang.IllegalStateException:状态应该是:打开

python - 在 python 中,如何让我自己的异常类在 shell 中漂亮地打印出来?

java - spring抽象="true"是什么意思?

java - 第三方类的AOP

java - 无法在本地主机 :8080/h2-console when using webflux 访问 H2 数据库

java - 模拟 WebClient post 方法失败