spring - 使用 Spring WebClient 时如何捕获 IOException?
问题描述
我正在做一个项目,我们正在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 文档中找出如何IOException
在使用时处理 'sWebClient
但找不到任何东西。
这里的方法是什么?
解决方案
最好的方法几乎肯定是处理反应流本身的所有错误。服务器响应错误通常最好通过使用exchange()
而不是retrieve()
手动处理响应来处理,而底层IOException
则通过使用onErrorResume()
等onErrorReturn()
可用于此目的的反应性运算符来处理。
但是,您提到您正在从阻塞代码迁移,所以我知道实际上这可能(尚未)出现在卡片上。如果您想坚持捕获异常:
但是由于我不想重写我们的内部代码来捕获 RuntimeException 级别但 WebClientException 级别的异常,这不是一个选项,我想知道如何做到这一点?
想要在 的保护伞下捕获所有传输错误WebClientException
并不是一个明智的选择。正如您所说,两者都不是RuntimeException
出于明显的原因而捕获的。
简化它的WebClientException
意思是“我连接到 URL 并毫无问题地向它发送了东西,但它告诉我要草草离开”(即它生成了一个错误代码而不是 200 响应。)
这可能是因为 404(找不到资源)、500(服务器错误)、418(您尝试连接到茶壶,而不是服务器)等。
IOException
另一方面意味着“甚至无法建立与此 URL 的连接”。这可能是因为连接被主动拒绝、域名无法解析、SSL 证书过期等。
两者并不相似,以这种方式对待它们会相当奇怪和令人困惑。
如果您想在同一个块中处理它们,那很好 - 天真地您可能只是这样做:
catch(WebClientException|IOException e) {
// do some stuff
}
...但您当然不能,因为IOException
已检查。(Java 中的反应式流不会抛出已检查的异常,每个已检查的异常都映射到 a RuntimeException
。)
但是,您可以将所有映射IOException
到UncheckedIOException
:
return webClient
.get()
.uri(someUri)
.retrieve()
.toEntity(SomeBusinessClass.class)
.onErrorMap(IOException.class, UncheckedIOException::new)
.block()
...然后要么做catch(WebClientException|UncheckedIOException ex)
,要么在单独的 catch 块中处理它们。
这当然不是从反应式思维方式处理异常的“好”方式,但如果您的目标是通过尽可能少的更改进行迁移,那么这可能就是您所追求的。
推荐阅读
- angular - 具有布尔值/布尔值“平均值”的对象(更好的解释)
- html - materializecss 中的响应式图像问题
- javascript - 循环访问分析工具库中的特定 JS 代码
- tsql - 数值无法识别
- google-apps-script - 添加输入字段并连接到表格
- npm - 在“npm install”和“yarn install”上自动调用“node-gyp rebuild”
- python - 如何从 Python 中的 yml 文件中提取特定信息并在数据框中使用它?
- pytorch - 带有权重的pytorch conv2d
- scala - 在scala中动态创建变量
- python - 使用 pandas 库时出现“return self._engine.get_loc(casted_key)”错误