【发布时间】:2021-08-13 14:03:51
【问题描述】:
我正在 Kotlin (1.4.30) 中使用 Spring WebFlux WebClient (Boot 2.4.3) 进行 get http 调用。当请求超时时,它会因异常而失败,但我想返回一个默认值。我看到在retrieve() 之后使用了对onError、onStatus 等的引用,但在我的情况下它们似乎不可用(仅body、toEntity、awaitExchange)
电话:
suspend fun conversation(id: String): Conversation =
client.get().uri("/conversation/{id}", id).retrieve().awaitBody()
带有连接和读取超时的 WebClient 配置:
fun webClient(url: String, connectTimeout: Int, readTimeout: Long, objectMapper: ObjectMapper): WebClient =
WebClient.builder()
.baseUrl(url)
.exchangeStrategies(
ExchangeStrategies.builder()
.codecs { configurer -> configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(objectMapper)) }
.build())
.clientConnector(
ReactorClientHttpConnector(
HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout)
.doOnConnected { connection ->
connection.addHandlerLast(ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS))
}))
.build()
响应模型:
@JsonIgnoreProperties(ignoreUnknown = true)
data class Conversation(
val replyTimestamp: Map<String, String>,
)
如何在超时而不是因异常而失败时返回默认响应(与空地图的对话)?
更新:
我在下面尝试了 JArgente 的建议:使用 awaitExchange 更新了调用,并设置了有效的 WireMock 响应,延迟时间(1010 毫秒)比超时时间(1000 毫秒)更长。
Result 仍然是 ReadTimeoutException,因此在这种情况下查看 http 状态代码无济于事。
private val defaultConversation = Conversation(emptyMap())
suspend fun conversation(id: String): Conversation =
client.get()
.uri("/conversation/{id}", id)
.awaitExchange {
response -> if (response.statusCode() == HttpStatus.OK) response.awaitBody() else defaultConversation
}
回复:
{
"replyTimestamp": {
"1": "2021-02-23T15:30:28.753Z",
"2": "2021-02-23T16:30:28.753Z"
}
}
模拟配置:
{
"mappings":
[
{
"priority": 1,
"request": {
"method": "GET",
"urlPathPattern": "/conversation/1"
},
"response": {
"status": 200,
"fixedDelayMilliseconds": 1010,
"headers": {
"content-type": "application/json;charset=utf-8"
},
"bodyFileName": "conversation1.json"
}
}
]
}
【问题讨论】:
-
当您使用协程时,您可以简单地使用 try-catch 来处理相关异常。
标签: spring kotlin spring-webflux spring-webclient